Linux user memory access API change (initial patch by Thayne Harbaugh)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@3583 c046a42c-6fe2-441c-8c8c-71466251a162
This commit is contained in:
parent
44f8625d23
commit
579a97f7ff
@ -260,7 +260,7 @@ endif
|
||||
|
||||
ifdef CONFIG_LINUX_USER
|
||||
OBJS= main.o syscall.o strace.o mmap.o signal.o path.o osdep.o thunk.o \
|
||||
elfload.o linuxload.o
|
||||
elfload.o linuxload.o uaccess.o
|
||||
LIBS+= $(AIOLIBS)
|
||||
ifdef TARGET_HAS_BFLT
|
||||
OBJS+= flatload.o
|
||||
|
52
arm-semi.c
52
arm-semi.c
@ -184,9 +184,11 @@ uint32_t do_arm_semihosting(CPUState *env)
|
||||
args = env->regs[1];
|
||||
switch (nr) {
|
||||
case SYS_OPEN:
|
||||
s = lock_user_string(ARG(0));
|
||||
if (!(s = lock_user_string(ARG(0))))
|
||||
/* FIXME - should this error code be -TARGET_EFAULT ? */
|
||||
return (uint32_t)-1;
|
||||
if (ARG(1) >= 12)
|
||||
return (uint32_t)-1;
|
||||
return (uint32_t)-1;
|
||||
if (strcmp(s, ":tt") == 0) {
|
||||
if (ARG(1) < 4)
|
||||
return STDIN_FILENO;
|
||||
@ -221,7 +223,9 @@ uint32_t do_arm_semihosting(CPUState *env)
|
||||
}
|
||||
}
|
||||
case SYS_WRITE0:
|
||||
s = lock_user_string(args);
|
||||
if (!(s = lock_user_string(args)))
|
||||
/* FIXME - should this error code be -TARGET_EFAULT ? */
|
||||
return (uint32_t)-1;
|
||||
len = strlen(s);
|
||||
if (use_gdb_syscalls()) {
|
||||
gdb_do_syscall(arm_semi_cb, "write,2,%x,%x\n", args, len);
|
||||
@ -238,7 +242,9 @@ uint32_t do_arm_semihosting(CPUState *env)
|
||||
gdb_do_syscall(arm_semi_cb, "write,%x,%x,%x", ARG(0), ARG(1), len);
|
||||
return env->regs[0];
|
||||
} else {
|
||||
s = lock_user(ARG(1), len, 1);
|
||||
if (!(s = lock_user(VERIFY_READ, ARG(1), len, 1)))
|
||||
/* FIXME - should this error code be -TARGET_EFAULT ? */
|
||||
return (uint32_t)-1;
|
||||
ret = set_swi_errno(ts, write(ARG(0), s, len));
|
||||
unlock_user(s, ARG(1), 0);
|
||||
if (ret == (uint32_t)-1)
|
||||
@ -252,7 +258,9 @@ uint32_t do_arm_semihosting(CPUState *env)
|
||||
gdb_do_syscall(arm_semi_cb, "read,%x,%x,%x", ARG(0), ARG(1), len);
|
||||
return env->regs[0];
|
||||
} else {
|
||||
s = lock_user(ARG(1), len, 0);
|
||||
if (!(s = lock_user(VERIFY_WRITE, ARG(1), len, 0)))
|
||||
/* FIXME - should this error code be -TARGET_EFAULT ? */
|
||||
return (uint32_t)-1;
|
||||
do
|
||||
ret = set_swi_errno(ts, read(ARG(0), s, len));
|
||||
while (ret == -1 && errno == EINTR);
|
||||
@ -301,7 +309,9 @@ uint32_t do_arm_semihosting(CPUState *env)
|
||||
gdb_do_syscall(arm_semi_cb, "unlink,%s", ARG(0), (int)ARG(1)+1);
|
||||
ret = env->regs[0];
|
||||
} else {
|
||||
s = lock_user_string(ARG(0));
|
||||
if (!(s = lock_user_string(ARG(0))))
|
||||
/* FIXME - should this error code be -TARGET_EFAULT ? */
|
||||
return (uint32_t)-1;
|
||||
ret = set_swi_errno(ts, remove(s));
|
||||
unlock_user(s, ARG(0), 0);
|
||||
}
|
||||
@ -315,9 +325,15 @@ uint32_t do_arm_semihosting(CPUState *env)
|
||||
char *s2;
|
||||
s = lock_user_string(ARG(0));
|
||||
s2 = lock_user_string(ARG(2));
|
||||
ret = set_swi_errno(ts, rename(s, s2));
|
||||
unlock_user(s2, ARG(2), 0);
|
||||
unlock_user(s, ARG(0), 0);
|
||||
if (!s || !s2)
|
||||
/* FIXME - should this error code be -TARGET_EFAULT ? */
|
||||
ret = (uint32_t)-1;
|
||||
else
|
||||
ret = set_swi_errno(ts, rename(s, s2));
|
||||
if (s2)
|
||||
unlock_user(s2, ARG(2), 0);
|
||||
if (s)
|
||||
unlock_user(s, ARG(0), 0);
|
||||
return ret;
|
||||
}
|
||||
case SYS_CLOCK:
|
||||
@ -329,7 +345,9 @@ uint32_t do_arm_semihosting(CPUState *env)
|
||||
gdb_do_syscall(arm_semi_cb, "system,%s", ARG(0), (int)ARG(1)+1);
|
||||
return env->regs[0];
|
||||
} else {
|
||||
s = lock_user_string(ARG(0));
|
||||
if (!(s = lock_user_string(ARG(0))))
|
||||
/* FIXME - should this error code be -TARGET_EFAULT ? */
|
||||
return (uint32_t)-1;
|
||||
ret = set_swi_errno(ts, system(s));
|
||||
unlock_user(s, ARG(0), 0);
|
||||
}
|
||||
@ -346,7 +364,11 @@ uint32_t do_arm_semihosting(CPUState *env)
|
||||
char **arg = ts->info->host_argv;
|
||||
int len = ARG(1);
|
||||
/* lock the buffer on the ARM side */
|
||||
char *cmdline_buffer = (char*)lock_user(ARG(0), len, 0);
|
||||
char *cmdline_buffer = (char*)lock_user(VERIFY_WRITE, ARG(0), len, 0);
|
||||
|
||||
if (!cmdline_buffer)
|
||||
/* FIXME - should this error code be -TARGET_EFAULT ? */
|
||||
return (uint32_t)-1;
|
||||
|
||||
s = cmdline_buffer;
|
||||
while (*arg && len > 2) {
|
||||
@ -402,7 +424,9 @@ uint32_t do_arm_semihosting(CPUState *env)
|
||||
ts->heap_limit = limit;
|
||||
}
|
||||
|
||||
ptr = lock_user(ARG(0), 16, 0);
|
||||
if (!(ptr = lock_user(VERIFY_WRITE, ARG(0), 16, 0)))
|
||||
/* FIXME - should this error code be -TARGET_EFAULT ? */
|
||||
return (uint32_t)-1;
|
||||
ptr[0] = tswap32(ts->heap_base);
|
||||
ptr[1] = tswap32(ts->heap_limit);
|
||||
ptr[2] = tswap32(ts->stack_base);
|
||||
@ -410,7 +434,9 @@ uint32_t do_arm_semihosting(CPUState *env)
|
||||
unlock_user(ptr, ARG(0), 16);
|
||||
#else
|
||||
limit = ram_size;
|
||||
ptr = lock_user(ARG(0), 16, 0);
|
||||
if (!(ptr = lock_user(VERIFY_WRITE, ARG(0), 16, 0)))
|
||||
/* FIXME - should this error code be -TARGET_EFAULT ? */
|
||||
return (uint32_t)-1;
|
||||
/* TODO: Make this use the limit of the loaded application. */
|
||||
ptr[0] = tswap32(limit / 2);
|
||||
ptr[1] = tswap32(limit);
|
||||
|
10
exec.c
10
exec.c
@ -2510,13 +2510,19 @@ void cpu_physical_memory_rw(target_phys_addr_t addr, uint8_t *buf,
|
||||
if (is_write) {
|
||||
if (!(flags & PAGE_WRITE))
|
||||
return;
|
||||
p = lock_user(addr, len, 0);
|
||||
/* XXX: this code should not depend on lock_user */
|
||||
if (!(p = lock_user(VERIFY_WRITE, addr, len, 0)))
|
||||
/* FIXME - should this return an error rather than just fail? */
|
||||
return;
|
||||
memcpy(p, buf, len);
|
||||
unlock_user(p, addr, len);
|
||||
} else {
|
||||
if (!(flags & PAGE_READ))
|
||||
return;
|
||||
p = lock_user(addr, len, 1);
|
||||
/* XXX: this code should not depend on lock_user */
|
||||
if (!(p = lock_user(VERIFY_READ, addr, len, 1)))
|
||||
/* FIXME - should this return an error rather than just fail? */
|
||||
return;
|
||||
memcpy(buf, p, len);
|
||||
unlock_user(p, addr, 0);
|
||||
}
|
||||
|
@ -677,7 +677,7 @@ static abi_ulong setup_arg_pages(abi_ulong p, struct linux_binprm *bprm,
|
||||
for (i = 0 ; i < MAX_ARG_PAGES ; i++) {
|
||||
if (bprm->page[i]) {
|
||||
info->rss++;
|
||||
|
||||
/* FIXME - check return value of memcpy_to_target() for failure */
|
||||
memcpy_to_target(stack_base, bprm->page[i], TARGET_PAGE_SIZE);
|
||||
free(bprm->page[i]);
|
||||
}
|
||||
@ -760,6 +760,7 @@ static abi_ulong create_elf_tables(abi_ulong p, int argc, int envc,
|
||||
size_t len = strlen(k_platform) + 1;
|
||||
sp -= (len + n - 1) & ~(n - 1);
|
||||
u_platform = sp;
|
||||
/* FIXME - check return value of memcpy_to_target() for failure */
|
||||
memcpy_to_target(sp, k_platform, len);
|
||||
}
|
||||
/*
|
||||
|
@ -108,7 +108,7 @@ int target_pread(int fd, abi_ulong ptr, abi_ulong len,
|
||||
void *buf;
|
||||
int ret;
|
||||
|
||||
buf = lock_user(ptr, len, 0);
|
||||
buf = lock_user(VERIFY_WRITE, ptr, len, 0);
|
||||
ret = pread(fd, buf, len, offset);
|
||||
unlock_user(buf, ptr, len);
|
||||
return ret;
|
||||
|
@ -13,14 +13,17 @@
|
||||
#define NGROUPS 32
|
||||
|
||||
/* ??? This should really be somewhere else. */
|
||||
void memcpy_to_target(abi_ulong dest, const void *src,
|
||||
unsigned long len)
|
||||
abi_long memcpy_to_target(abi_ulong dest, const void *src,
|
||||
unsigned long len)
|
||||
{
|
||||
void *host_ptr;
|
||||
|
||||
host_ptr = lock_user(dest, len, 0);
|
||||
host_ptr = lock_user(VERIFY_WRITE, dest, len, 0);
|
||||
if (!host_ptr)
|
||||
return -TARGET_EFAULT;
|
||||
memcpy(host_ptr, src, len);
|
||||
unlock_user(host_ptr, dest, 1);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int in_group_p(gid_t g)
|
||||
|
@ -146,8 +146,8 @@ int load_elf_binary_multi(struct linux_binprm *bprm,
|
||||
struct image_info *info);
|
||||
#endif
|
||||
|
||||
void memcpy_to_target(abi_ulong dest, const void *src,
|
||||
unsigned long len);
|
||||
abi_long memcpy_to_target(abi_ulong dest, const void *src,
|
||||
unsigned long len);
|
||||
void target_set_brk(abi_ulong new_brk);
|
||||
abi_long do_brk(abi_ulong new_brk);
|
||||
void syscall_init(void);
|
||||
@ -179,9 +179,7 @@ void host_to_target_siginfo(target_siginfo_t *tinfo, const siginfo_t *info);
|
||||
void target_to_host_siginfo(siginfo_t *info, const target_siginfo_t *tinfo);
|
||||
long do_sigreturn(CPUState *env);
|
||||
long do_rt_sigreturn(CPUState *env);
|
||||
int do_sigaltstack(const struct target_sigaltstack *uss,
|
||||
struct target_sigaltstack *uoss,
|
||||
abi_ulong sp);
|
||||
abi_long do_sigaltstack(abi_ulong uss_addr, abi_ulong uoss_addr, abi_ulong sp);
|
||||
|
||||
#ifdef TARGET_I386
|
||||
/* vm86.c */
|
||||
@ -207,12 +205,15 @@ int target_msync(abi_ulong start, abi_ulong len, int flags);
|
||||
/* user access */
|
||||
|
||||
#define VERIFY_READ 0
|
||||
#define VERIFY_WRITE 1
|
||||
#define VERIFY_WRITE 1 /* implies read access */
|
||||
|
||||
#define access_ok(type,addr,size) \
|
||||
(page_check_range((target_ulong)addr,size,(type==VERIFY_READ)?PAGE_READ:PAGE_WRITE)==0)
|
||||
|
||||
/* NOTE __get_user and __put_user use host pointers and don't check access. */
|
||||
/* These are usually used to access struct data members once the
|
||||
* struct has been locked - usually with lock_user_struct().
|
||||
*/
|
||||
#define __put_user(x, hptr)\
|
||||
({\
|
||||
int size = sizeof(*hptr);\
|
||||
@ -257,26 +258,44 @@ int target_msync(abi_ulong start, abi_ulong len, int flags);
|
||||
0;\
|
||||
})
|
||||
|
||||
#define put_user(x,ptr)\
|
||||
({\
|
||||
int __ret;\
|
||||
if (access_ok(VERIFY_WRITE, ptr, sizeof(*ptr)))\
|
||||
__ret = __put_user(x, ptr);\
|
||||
else\
|
||||
__ret = -EFAULT;\
|
||||
__ret;\
|
||||
/* put_user()/get_user() take a guest address and check access */
|
||||
/* These are usually used to access an atomic data type, such as an int,
|
||||
* that has been passed by address. These internally perform locking
|
||||
* and unlocking on the data type.
|
||||
*/
|
||||
#define put_user(x, gaddr, target_type) \
|
||||
({ \
|
||||
abi_ulong __gaddr = (gaddr); \
|
||||
target_type *__hptr; \
|
||||
abi_long __ret; \
|
||||
if ((__hptr = lock_user(VERIFY_WRITE, __gaddr, sizeof(target_type), 0))) { \
|
||||
__ret = __put_user((x), __hptr); \
|
||||
unlock_user(__hptr, __gaddr, sizeof(target_type)); \
|
||||
} else \
|
||||
__ret = -TARGET_EFAULT; \
|
||||
__ret; \
|
||||
})
|
||||
|
||||
#define get_user(x,ptr)\
|
||||
({\
|
||||
int __ret;\
|
||||
if (access_ok(VERIFY_READ, ptr, sizeof(*ptr)))\
|
||||
__ret = __get_user(x, ptr);\
|
||||
else\
|
||||
__ret = -EFAULT;\
|
||||
__ret;\
|
||||
#define get_user(x, gaddr, target_type) \
|
||||
({ \
|
||||
abi_ulong __gaddr = (gaddr); \
|
||||
target_type *__hptr; \
|
||||
abi_long __ret; \
|
||||
if ((__hptr = lock_user(VERIFY_READ, __gaddr, sizeof(target_type), 1))) { \
|
||||
__ret = __get_user((x), __hptr); \
|
||||
unlock_user(__hptr, __gaddr, 0); \
|
||||
} else \
|
||||
__ret = -TARGET_EFAULT; \
|
||||
__ret; \
|
||||
})
|
||||
|
||||
/* copy_from_user() and copy_to_user() are usually used to copy data
|
||||
* buffers between the target and host. These internally perform
|
||||
* locking/unlocking of the memory.
|
||||
*/
|
||||
abi_long copy_from_user(void *hptr, abi_ulong gaddr, size_t len);
|
||||
abi_long copy_to_user(abi_ulong gaddr, void *hptr, size_t len);
|
||||
|
||||
/* Functions for accessing guest memory. The tget and tput functions
|
||||
read/write single values, byteswapping as neccessary. The lock_user
|
||||
gets a pointer to a contiguous area of guest memory, but does not perform
|
||||
@ -285,53 +304,61 @@ int target_msync(abi_ulong start, abi_ulong len, int flags);
|
||||
|
||||
/* Lock an area of guest memory into the host. If copy is true then the
|
||||
host area will have the same contents as the guest. */
|
||||
static inline void *lock_user(abi_ulong guest_addr, long len, int copy)
|
||||
static inline void *lock_user(int type, abi_ulong guest_addr, long len, int copy)
|
||||
{
|
||||
if (!access_ok(type, guest_addr, len))
|
||||
return NULL;
|
||||
#ifdef DEBUG_REMAP
|
||||
void *addr;
|
||||
addr = malloc(len);
|
||||
if (copy)
|
||||
memcpy(addr, g2h(guest_addr), len);
|
||||
else
|
||||
memset(addr, 0, len);
|
||||
return addr;
|
||||
{
|
||||
void *addr;
|
||||
addr = malloc(len);
|
||||
if (copy)
|
||||
memcpy(addr, g2h(guest_addr), len);
|
||||
else
|
||||
memset(addr, 0, len);
|
||||
return addr;
|
||||
}
|
||||
#else
|
||||
return g2h(guest_addr);
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Unlock an area of guest memory. The first LEN bytes must be flushed back
|
||||
to guest memory. */
|
||||
static inline void unlock_user(void *host_addr, abi_ulong guest_addr,
|
||||
/* Unlock an area of guest memory. The first LEN bytes must be
|
||||
flushed back to guest memory. host_ptr = NULL is explicitely
|
||||
allowed and does nothing. */
|
||||
static inline void unlock_user(void *host_ptr, abi_ulong guest_addr,
|
||||
long len)
|
||||
{
|
||||
|
||||
#ifdef DEBUG_REMAP
|
||||
if (host_addr == g2h(guest_addr))
|
||||
if (!host_ptr)
|
||||
return;
|
||||
if (host_ptr == g2h(guest_addr))
|
||||
return;
|
||||
if (len > 0)
|
||||
memcpy(g2h(guest_addr), host_addr, len);
|
||||
free(host_addr);
|
||||
memcpy(g2h(guest_ptr), host_ptr, len);
|
||||
free(host_ptr);
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Return the length of a string in target memory. */
|
||||
static inline int target_strlen(abi_ulong ptr)
|
||||
{
|
||||
return strlen(g2h(ptr));
|
||||
}
|
||||
/* Return the length of a string in target memory or -TARGET_EFAULT if
|
||||
access error. */
|
||||
abi_long target_strlen(abi_ulong gaddr);
|
||||
|
||||
/* Like lock_user but for null terminated strings. */
|
||||
static inline void *lock_user_string(abi_ulong guest_addr)
|
||||
{
|
||||
long len;
|
||||
len = target_strlen(guest_addr) + 1;
|
||||
return lock_user(guest_addr, len, 1);
|
||||
abi_long len;
|
||||
len = target_strlen(guest_addr);
|
||||
if (len < 0)
|
||||
return NULL;
|
||||
return lock_user(VERIFY_READ, guest_addr, (long)(len + 1), 1);
|
||||
}
|
||||
|
||||
/* Helper macros for locking/ulocking a target struct. */
|
||||
#define lock_user_struct(host_ptr, guest_addr, copy) \
|
||||
host_ptr = lock_user(guest_addr, sizeof(*host_ptr), copy)
|
||||
#define unlock_user_struct(host_ptr, guest_addr, copy) \
|
||||
#define lock_user_struct(type, host_ptr, guest_addr, copy) \
|
||||
(host_ptr = lock_user(type, guest_addr, sizeof(*host_ptr), copy))
|
||||
#define unlock_user_struct(host_ptr, guest_addr, copy) \
|
||||
unlock_user(host_ptr, guest_addr, (copy) ? sizeof(*host_ptr) : 0)
|
||||
|
||||
#define tget8(addr) ldub(addr)
|
||||
|
@ -435,31 +435,32 @@ static void host_signal_handler(int host_signum, siginfo_t *info,
|
||||
}
|
||||
|
||||
/* do_sigaltstack() returns target values and errnos. */
|
||||
int do_sigaltstack(const struct target_sigaltstack *uss,
|
||||
struct target_sigaltstack *uoss,
|
||||
abi_ulong sp)
|
||||
/* compare linux/kernel/signal.c:do_sigaltstack() */
|
||||
abi_long do_sigaltstack(abi_ulong uss_addr, abi_ulong uoss_addr, abi_ulong sp)
|
||||
{
|
||||
int ret;
|
||||
struct target_sigaltstack oss;
|
||||
|
||||
/* XXX: test errors */
|
||||
if(uoss)
|
||||
if(uoss_addr)
|
||||
{
|
||||
__put_user(target_sigaltstack_used.ss_sp, &oss.ss_sp);
|
||||
__put_user(target_sigaltstack_used.ss_size, &oss.ss_size);
|
||||
__put_user(sas_ss_flags(sp), &oss.ss_flags);
|
||||
}
|
||||
|
||||
if(uss)
|
||||
if(uss_addr)
|
||||
{
|
||||
struct target_sigaltstack ss;
|
||||
struct target_sigaltstack *uss;
|
||||
struct target_sigaltstack ss;
|
||||
|
||||
ret = -TARGET_EFAULT;
|
||||
if (!access_ok(VERIFY_READ, uss, sizeof(*uss))
|
||||
if (!lock_user_struct(VERIFY_READ, uss, uss_addr, 1)
|
||||
|| __get_user(ss.ss_sp, &uss->ss_sp)
|
||||
|| __get_user(ss.ss_size, &uss->ss_size)
|
||||
|| __get_user(ss.ss_flags, &uss->ss_flags))
|
||||
goto out;
|
||||
unlock_user_struct(uss, uss_addr, 0);
|
||||
|
||||
ret = -TARGET_EPERM;
|
||||
if (on_sig_stack(sp))
|
||||
@ -484,11 +485,10 @@ int do_sigaltstack(const struct target_sigaltstack *uss,
|
||||
target_sigaltstack_used.ss_size = ss.ss_size;
|
||||
}
|
||||
|
||||
if (uoss) {
|
||||
if (uoss_addr) {
|
||||
ret = -TARGET_EFAULT;
|
||||
if (!access_ok(VERIFY_WRITE, uoss, sizeof(oss)))
|
||||
if (copy_to_user(uoss_addr, &oss, sizeof(oss)))
|
||||
goto out;
|
||||
memcpy(uoss, &oss, sizeof(oss));
|
||||
}
|
||||
|
||||
ret = 0;
|
||||
@ -671,6 +671,7 @@ setup_sigcontext(struct target_sigcontext *sc, struct target_fpstate *fpstate,
|
||||
{
|
||||
int err = 0;
|
||||
|
||||
/* already locked in setup_frame() */
|
||||
err |= __put_user(env->segs[R_GS].selector, (unsigned int *)&sc->gs);
|
||||
err |= __put_user(env->segs[R_FS].selector, (unsigned int *)&sc->fs);
|
||||
err |= __put_user(env->segs[R_ES].selector, (unsigned int *)&sc->es);
|
||||
@ -706,7 +707,7 @@ setup_sigcontext(struct target_sigcontext *sc, struct target_fpstate *fpstate,
|
||||
* Determine which stack to use..
|
||||
*/
|
||||
|
||||
static inline void *
|
||||
static inline abi_ulong
|
||||
get_sigframe(struct emulated_sigaction *ka, CPUX86State *env, size_t frame_size)
|
||||
{
|
||||
unsigned long esp;
|
||||
@ -726,19 +727,22 @@ get_sigframe(struct emulated_sigaction *ka, CPUX86State *env, size_t frame_size)
|
||||
ka->sa.sa_restorer) {
|
||||
esp = (unsigned long) ka->sa.sa_restorer;
|
||||
}
|
||||
return g2h((esp - frame_size) & -8ul);
|
||||
return (esp - frame_size) & -8ul;
|
||||
}
|
||||
|
||||
/* compare linux/arch/i386/kernel/signal.c:setup_frame() */
|
||||
static void setup_frame(int sig, struct emulated_sigaction *ka,
|
||||
target_sigset_t *set, CPUX86State *env)
|
||||
{
|
||||
abi_ulong frame_addr;
|
||||
struct sigframe *frame;
|
||||
int i, err = 0;
|
||||
|
||||
frame = get_sigframe(ka, env, sizeof(*frame));
|
||||
frame_addr = get_sigframe(ka, env, sizeof(*frame));
|
||||
|
||||
if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame)))
|
||||
if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0))
|
||||
goto give_sigsegv;
|
||||
|
||||
err |= __put_user((/*current->exec_domain
|
||||
&& current->exec_domain->signal_invmap
|
||||
&& sig < 32
|
||||
@ -786,24 +790,29 @@ static void setup_frame(int sig, struct emulated_sigaction *ka,
|
||||
cpu_x86_load_seg(env, R_CS, __USER_CS);
|
||||
env->eflags &= ~TF_MASK;
|
||||
|
||||
unlock_user_struct(frame, frame_addr, 1);
|
||||
|
||||
return;
|
||||
|
||||
give_sigsegv:
|
||||
unlock_user_struct(frame, frame_addr, 1);
|
||||
if (sig == TARGET_SIGSEGV)
|
||||
ka->sa._sa_handler = TARGET_SIG_DFL;
|
||||
force_sig(TARGET_SIGSEGV /* , current */);
|
||||
}
|
||||
|
||||
/* compare linux/arch/i386/kernel/signal.c:setup_rt_frame() */
|
||||
static void setup_rt_frame(int sig, struct emulated_sigaction *ka,
|
||||
target_siginfo_t *info,
|
||||
target_sigset_t *set, CPUX86State *env)
|
||||
{
|
||||
abi_ulong frame_addr;
|
||||
struct rt_sigframe *frame;
|
||||
int i, err = 0;
|
||||
|
||||
frame = get_sigframe(ka, env, sizeof(*frame));
|
||||
frame_addr = get_sigframe(ka, env, sizeof(*frame));
|
||||
|
||||
if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame)))
|
||||
if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0))
|
||||
goto give_sigsegv;
|
||||
|
||||
err |= __put_user((/*current->exec_domain
|
||||
@ -859,9 +868,12 @@ static void setup_rt_frame(int sig, struct emulated_sigaction *ka,
|
||||
cpu_x86_load_seg(env, R_CS, __USER_CS);
|
||||
env->eflags &= ~TF_MASK;
|
||||
|
||||
unlock_user_struct(frame, frame_addr, 1);
|
||||
|
||||
return;
|
||||
|
||||
give_sigsegv:
|
||||
unlock_user_struct(frame, frame_addr, 1);
|
||||
if (sig == TARGET_SIGSEGV)
|
||||
ka->sa._sa_handler = TARGET_SIG_DFL;
|
||||
force_sig(TARGET_SIGSEGV /* , current */);
|
||||
@ -918,7 +930,8 @@ badframe:
|
||||
|
||||
long do_sigreturn(CPUX86State *env)
|
||||
{
|
||||
struct sigframe *frame = (struct sigframe *)g2h(env->regs[R_ESP] - 8);
|
||||
struct sigframe *frame;
|
||||
abi_ulong frame_addr = env->regs[R_ESP] - 8;
|
||||
target_sigset_t target_set;
|
||||
sigset_t set;
|
||||
int eax, i;
|
||||
@ -926,6 +939,8 @@ long do_sigreturn(CPUX86State *env)
|
||||
#if defined(DEBUG_SIGNAL)
|
||||
fprintf(stderr, "do_sigreturn\n");
|
||||
#endif
|
||||
if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1))
|
||||
goto badframe;
|
||||
/* set blocked signals */
|
||||
if (__get_user(target_set.sig[0], &frame->sc.oldmask))
|
||||
goto badframe;
|
||||
@ -940,9 +955,11 @@ long do_sigreturn(CPUX86State *env)
|
||||
/* restore registers */
|
||||
if (restore_sigcontext(env, &frame->sc, &eax))
|
||||
goto badframe;
|
||||
unlock_user_struct(frame, frame_addr, 0);
|
||||
return eax;
|
||||
|
||||
badframe:
|
||||
unlock_user_struct(frame, frame_addr, 0);
|
||||
force_sig(TARGET_SIGSEGV);
|
||||
return 0;
|
||||
}
|
||||
@ -963,7 +980,7 @@ long do_rt_sigreturn(CPUX86State *env)
|
||||
if (restore_sigcontext(env, &frame->uc.tuc_mcontext, &eax))
|
||||
goto badframe;
|
||||
|
||||
if (do_sigaltstack(&frame->uc.tuc_stack, NULL, get_sp_from_cpustate(env)) == -EFAULT)
|
||||
if (do_sigaltstack(h2g(&frame->uc.tuc_stack), 0, get_sp_from_cpustate(env)) == -EFAULT)
|
||||
goto badframe;
|
||||
|
||||
return eax;
|
||||
@ -1086,7 +1103,7 @@ setup_sigcontext(struct target_sigcontext *sc, /*struct _fpstate *fpstate,*/
|
||||
return err;
|
||||
}
|
||||
|
||||
static inline void *
|
||||
static inline abi_ulong
|
||||
get_sigframe(struct emulated_sigaction *ka, CPUState *regs, int framesize)
|
||||
{
|
||||
unsigned long sp = regs->regs[13];
|
||||
@ -1099,7 +1116,7 @@ get_sigframe(struct emulated_sigaction *ka, CPUState *regs, int framesize)
|
||||
/*
|
||||
* ATPCS B01 mandates 8-byte alignment
|
||||
*/
|
||||
return g2h((sp - framesize) & ~7);
|
||||
return (sp - framesize) & ~7;
|
||||
}
|
||||
|
||||
static int
|
||||
@ -1167,33 +1184,43 @@ setup_return(CPUState *env, struct emulated_sigaction *ka,
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* compare linux/arch/arm/kernel/signal.c:setup_frame() */
|
||||
static void setup_frame(int usig, struct emulated_sigaction *ka,
|
||||
target_sigset_t *set, CPUState *regs)
|
||||
{
|
||||
struct sigframe *frame = get_sigframe(ka, regs, sizeof(*frame));
|
||||
struct sigframe *frame;
|
||||
abi_ulong frame_addr = get_sigframe(ka, regs, sizeof(*frame));
|
||||
int i, err = 0;
|
||||
|
||||
if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0))
|
||||
return;
|
||||
|
||||
err |= setup_sigcontext(&frame->sc, /*&frame->fpstate,*/ regs, set->sig[0]);
|
||||
|
||||
for(i = 1; i < TARGET_NSIG_WORDS; i++) {
|
||||
if (__put_user(set->sig[i], &frame->extramask[i - 1]))
|
||||
return;
|
||||
goto end;
|
||||
}
|
||||
|
||||
if (err == 0)
|
||||
err = setup_return(regs, ka, &frame->retcode, frame, usig);
|
||||
|
||||
end:
|
||||
unlock_user_struct(frame, frame_addr, 1);
|
||||
// return err;
|
||||
}
|
||||
|
||||
/* compare linux/arch/arm/kernel/signal.c:setup_rt_frame() */
|
||||
static void setup_rt_frame(int usig, struct emulated_sigaction *ka,
|
||||
target_siginfo_t *info,
|
||||
target_sigset_t *set, CPUState *env)
|
||||
{
|
||||
struct rt_sigframe *frame = get_sigframe(ka, env, sizeof(*frame));
|
||||
struct rt_sigframe *frame;
|
||||
abi_ulong frame_addr = get_sigframe(ka, env, sizeof(*frame));
|
||||
struct target_sigaltstack stack;
|
||||
int i, err = 0;
|
||||
|
||||
if (!access_ok(VERIFY_WRITE, frame, sizeof (*frame)))
|
||||
if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0))
|
||||
return /* 1 */;
|
||||
|
||||
__put_user_error(&frame->info, (abi_ulong *)&frame->pinfo, err);
|
||||
@ -1207,16 +1234,13 @@ static void setup_rt_frame(int usig, struct emulated_sigaction *ka,
|
||||
__put_user(target_sigaltstack_used.ss_sp, &stack.ss_sp);
|
||||
__put_user(target_sigaltstack_used.ss_size, &stack.ss_size);
|
||||
__put_user(sas_ss_flags(get_sp_from_cpustate(env)), &stack.ss_flags);
|
||||
if (!access_ok(VERIFY_WRITE, &frame->uc.tuc_stack, sizeof(stack)))
|
||||
err = 1;
|
||||
else
|
||||
memcpy(&frame->uc.tuc_stack, &stack, sizeof(stack));
|
||||
err |= copy_to_user(&frame->uc.tuc_stack, &stack, sizeof(stack));
|
||||
|
||||
err |= setup_sigcontext(&frame->uc.tuc_mcontext, /*&frame->fpstate,*/
|
||||
env, set->sig[0]);
|
||||
for(i = 0; i < TARGET_NSIG_WORDS; i++) {
|
||||
if (__put_user(set->sig[i], &frame->uc.tuc_sigmask.sig[i]))
|
||||
return;
|
||||
goto end;
|
||||
}
|
||||
|
||||
if (err == 0)
|
||||
@ -1232,6 +1256,9 @@ static void setup_rt_frame(int usig, struct emulated_sigaction *ka,
|
||||
env->regs[2] = (abi_ulong)frame->puc;
|
||||
}
|
||||
|
||||
end:
|
||||
unlock_user_struct(frame, frame_addr, 1);
|
||||
|
||||
// return err;
|
||||
}
|
||||
|
||||
@ -1338,7 +1365,7 @@ long do_rt_sigreturn(CPUState *env)
|
||||
if (restore_sigcontext(env, &frame->uc.tuc_mcontext))
|
||||
goto badframe;
|
||||
|
||||
if (do_sigaltstack(&frame->uc.tuc_stack, NULL, get_sp_from_cpustate(env)) == -EFAULT)
|
||||
if (do_sigaltstack(h2g(&frame->uc.tuc_stack), 0, get_sp_from_cpustate(env)) == -EFAULT)
|
||||
goto badframe;
|
||||
|
||||
#if 0
|
||||
@ -1788,8 +1815,8 @@ void sparc64_set_context(CPUSPARCState *env)
|
||||
abi_ulong *src, *dst;
|
||||
|
||||
grp = &ucp->uc_mcontext.mc_gregs;
|
||||
err = get_user(pc, &((*grp)[MC_PC]));
|
||||
err |= get_user(npc, &((*grp)[MC_NPC]));
|
||||
err = __get_user(pc, &((*grp)[MC_PC]));
|
||||
err |= __get_user(npc, &((*grp)[MC_NPC]));
|
||||
if (err || ((pc | npc) & 3))
|
||||
goto do_sigsegv;
|
||||
if (env->regwptr[UREG_I1]) {
|
||||
@ -1797,14 +1824,14 @@ void sparc64_set_context(CPUSPARCState *env)
|
||||
sigset_t set;
|
||||
|
||||
if (TARGET_NSIG_WORDS == 1) {
|
||||
if (get_user(target_set.sig[0], &ucp->uc_sigmask.sig[0]))
|
||||
if (__get_user(target_set.sig[0], &ucp->uc_sigmask.sig[0]))
|
||||
goto do_sigsegv;
|
||||
} else {
|
||||
src = &ucp->uc_sigmask;
|
||||
dst = &target_set;
|
||||
for (i = 0; i < sizeof(target_sigset_t) / sizeof(abi_ulong);
|
||||
i++, dst++, src++)
|
||||
err |= get_user(dst, src);
|
||||
err |= __get_user(dst, src);
|
||||
if (err)
|
||||
goto do_sigsegv;
|
||||
}
|
||||
@ -1813,44 +1840,44 @@ void sparc64_set_context(CPUSPARCState *env)
|
||||
}
|
||||
env->pc = pc;
|
||||
env->npc = npc;
|
||||
err |= get_user(env->y, &((*grp)[MC_Y]));
|
||||
err |= get_user(tstate, &((*grp)[MC_TSTATE]));
|
||||
err |= __get_user(env->y, &((*grp)[MC_Y]));
|
||||
err |= __get_user(tstate, &((*grp)[MC_TSTATE]));
|
||||
env->asi = (tstate >> 24) & 0xff;
|
||||
PUT_CCR(env, tstate >> 32);
|
||||
PUT_CWP64(env, tstate & 0x1f);
|
||||
err |= get_user(env->gregs[1], (&(*grp)[MC_G1]));
|
||||
err |= get_user(env->gregs[2], (&(*grp)[MC_G2]));
|
||||
err |= get_user(env->gregs[3], (&(*grp)[MC_G3]));
|
||||
err |= get_user(env->gregs[4], (&(*grp)[MC_G4]));
|
||||
err |= get_user(env->gregs[5], (&(*grp)[MC_G5]));
|
||||
err |= get_user(env->gregs[6], (&(*grp)[MC_G6]));
|
||||
err |= get_user(env->gregs[7], (&(*grp)[MC_G7]));
|
||||
err |= get_user(env->regwptr[UREG_I0], (&(*grp)[MC_O0]));
|
||||
err |= get_user(env->regwptr[UREG_I1], (&(*grp)[MC_O1]));
|
||||
err |= get_user(env->regwptr[UREG_I2], (&(*grp)[MC_O2]));
|
||||
err |= get_user(env->regwptr[UREG_I3], (&(*grp)[MC_O3]));
|
||||
err |= get_user(env->regwptr[UREG_I4], (&(*grp)[MC_O4]));
|
||||
err |= get_user(env->regwptr[UREG_I5], (&(*grp)[MC_O5]));
|
||||
err |= get_user(env->regwptr[UREG_I6], (&(*grp)[MC_O6]));
|
||||
err |= get_user(env->regwptr[UREG_I7], (&(*grp)[MC_O7]));
|
||||
err |= __get_user(env->gregs[1], (&(*grp)[MC_G1]));
|
||||
err |= __get_user(env->gregs[2], (&(*grp)[MC_G2]));
|
||||
err |= __get_user(env->gregs[3], (&(*grp)[MC_G3]));
|
||||
err |= __get_user(env->gregs[4], (&(*grp)[MC_G4]));
|
||||
err |= __get_user(env->gregs[5], (&(*grp)[MC_G5]));
|
||||
err |= __get_user(env->gregs[6], (&(*grp)[MC_G6]));
|
||||
err |= __get_user(env->gregs[7], (&(*grp)[MC_G7]));
|
||||
err |= __get_user(env->regwptr[UREG_I0], (&(*grp)[MC_O0]));
|
||||
err |= __get_user(env->regwptr[UREG_I1], (&(*grp)[MC_O1]));
|
||||
err |= __get_user(env->regwptr[UREG_I2], (&(*grp)[MC_O2]));
|
||||
err |= __get_user(env->regwptr[UREG_I3], (&(*grp)[MC_O3]));
|
||||
err |= __get_user(env->regwptr[UREG_I4], (&(*grp)[MC_O4]));
|
||||
err |= __get_user(env->regwptr[UREG_I5], (&(*grp)[MC_O5]));
|
||||
err |= __get_user(env->regwptr[UREG_I6], (&(*grp)[MC_O6]));
|
||||
err |= __get_user(env->regwptr[UREG_I7], (&(*grp)[MC_O7]));
|
||||
|
||||
err |= get_user(fp, &(ucp->uc_mcontext.mc_fp));
|
||||
err |= get_user(i7, &(ucp->uc_mcontext.mc_i7));
|
||||
err |= put_user(fp,
|
||||
(&(((struct target_reg_window *)(TARGET_STACK_BIAS+env->regwptr[UREG_I6]))->ins[6])));
|
||||
err |= put_user(i7,
|
||||
(&(((struct target_reg_window *)(TARGET_STACK_BIAS+env->regwptr[UREG_I6]))->ins[7])));
|
||||
err |= __get_user(fp, &(ucp->uc_mcontext.mc_fp));
|
||||
err |= __get_user(i7, &(ucp->uc_mcontext.mc_i7));
|
||||
err |= __put_user(fp,
|
||||
(&(((struct target_reg_window *)(TARGET_STACK_BIAS+env->regwptr[UREG_I6]))->ins[6])));
|
||||
err |= __put_user(i7,
|
||||
(&(((struct target_reg_window *)(TARGET_STACK_BIAS+env->regwptr[UREG_I6]))->ins[7])));
|
||||
|
||||
err |= get_user(fenab, &(ucp->uc_mcontext.mc_fpregs.mcfpu_enab));
|
||||
err |= get_user(env->fprs, &(ucp->uc_mcontext.mc_fpregs.mcfpu_fprs));
|
||||
err |= __get_user(fenab, &(ucp->uc_mcontext.mc_fpregs.mcfpu_enab));
|
||||
err |= __get_user(env->fprs, &(ucp->uc_mcontext.mc_fpregs.mcfpu_fprs));
|
||||
src = &(ucp->uc_mcontext.mc_fpregs.mcfpu_fregs);
|
||||
dst = &env->fpr;
|
||||
for (i = 0; i < 64; i++, dst++, src++)
|
||||
err |= get_user(dst, src);
|
||||
err |= get_user(env->fsr,
|
||||
&(ucp->uc_mcontext.mc_fpregs.mcfpu_fsr));
|
||||
err |= get_user(env->gsr,
|
||||
&(ucp->uc_mcontext.mc_fpregs.mcfpu_gsr));
|
||||
err |= __get_user(dst, src);
|
||||
err |= __get_user(env->fsr,
|
||||
&(ucp->uc_mcontext.mc_fpregs.mcfpu_fsr));
|
||||
err |= __get_user(env->gsr,
|
||||
&(ucp->uc_mcontext.mc_fpregs.mcfpu_gsr));
|
||||
if (err)
|
||||
goto do_sigsegv;
|
||||
|
||||
@ -1884,52 +1911,52 @@ void sparc64_get_context(CPUSPARCState *env)
|
||||
sigprocmask(0, NULL, &set);
|
||||
host_to_target_sigset_internal(&target_set, &set);
|
||||
if (TARGET_NSIG_WORDS == 1)
|
||||
err |= put_user(target_set.sig[0],
|
||||
(abi_ulong *)&ucp->uc_sigmask);
|
||||
err |= __put_user(target_set.sig[0],
|
||||
(abi_ulong *)&ucp->uc_sigmask);
|
||||
else {
|
||||
src = &target_set;
|
||||
dst = &ucp->uc_sigmask;
|
||||
for (i = 0; i < sizeof(target_sigset_t) / sizeof(abi_ulong);
|
||||
i++, dst++, src++)
|
||||
err |= put_user(src, dst);
|
||||
err |= __put_user(src, dst);
|
||||
if (err)
|
||||
goto do_sigsegv;
|
||||
}
|
||||
|
||||
err |= put_user(env->tstate, &((*grp)[MC_TSTATE]));
|
||||
err |= put_user(env->pc, &((*grp)[MC_PC]));
|
||||
err |= put_user(env->npc, &((*grp)[MC_NPC]));
|
||||
err |= put_user(env->y, &((*grp)[MC_Y]));
|
||||
err |= put_user(env->gregs[1], &((*grp)[MC_G1]));
|
||||
err |= put_user(env->gregs[2], &((*grp)[MC_G2]));
|
||||
err |= put_user(env->gregs[3], &((*grp)[MC_G3]));
|
||||
err |= put_user(env->gregs[4], &((*grp)[MC_G4]));
|
||||
err |= put_user(env->gregs[5], &((*grp)[MC_G5]));
|
||||
err |= put_user(env->gregs[6], &((*grp)[MC_G6]));
|
||||
err |= put_user(env->gregs[7], &((*grp)[MC_G7]));
|
||||
err |= put_user(env->regwptr[UREG_I0], &((*grp)[MC_O0]));
|
||||
err |= put_user(env->regwptr[UREG_I1], &((*grp)[MC_O1]));
|
||||
err |= put_user(env->regwptr[UREG_I2], &((*grp)[MC_O2]));
|
||||
err |= put_user(env->regwptr[UREG_I3], &((*grp)[MC_O3]));
|
||||
err |= put_user(env->regwptr[UREG_I4], &((*grp)[MC_O4]));
|
||||
err |= put_user(env->regwptr[UREG_I5], &((*grp)[MC_O5]));
|
||||
err |= put_user(env->regwptr[UREG_I6], &((*grp)[MC_O6]));
|
||||
err |= put_user(env->regwptr[UREG_I7], &((*grp)[MC_O7]));
|
||||
err |= __put_user(env->tstate, &((*grp)[MC_TSTATE]));
|
||||
err |= __put_user(env->pc, &((*grp)[MC_PC]));
|
||||
err |= __put_user(env->npc, &((*grp)[MC_NPC]));
|
||||
err |= __put_user(env->y, &((*grp)[MC_Y]));
|
||||
err |= __put_user(env->gregs[1], &((*grp)[MC_G1]));
|
||||
err |= __put_user(env->gregs[2], &((*grp)[MC_G2]));
|
||||
err |= __put_user(env->gregs[3], &((*grp)[MC_G3]));
|
||||
err |= __put_user(env->gregs[4], &((*grp)[MC_G4]));
|
||||
err |= __put_user(env->gregs[5], &((*grp)[MC_G5]));
|
||||
err |= __put_user(env->gregs[6], &((*grp)[MC_G6]));
|
||||
err |= __put_user(env->gregs[7], &((*grp)[MC_G7]));
|
||||
err |= __put_user(env->regwptr[UREG_I0], &((*grp)[MC_O0]));
|
||||
err |= __put_user(env->regwptr[UREG_I1], &((*grp)[MC_O1]));
|
||||
err |= __put_user(env->regwptr[UREG_I2], &((*grp)[MC_O2]));
|
||||
err |= __put_user(env->regwptr[UREG_I3], &((*grp)[MC_O3]));
|
||||
err |= __put_user(env->regwptr[UREG_I4], &((*grp)[MC_O4]));
|
||||
err |= __put_user(env->regwptr[UREG_I5], &((*grp)[MC_O5]));
|
||||
err |= __put_user(env->regwptr[UREG_I6], &((*grp)[MC_O6]));
|
||||
err |= __put_user(env->regwptr[UREG_I7], &((*grp)[MC_O7]));
|
||||
|
||||
err |= get_user(fp,
|
||||
(&(((struct target_reg_window *)(TARGET_STACK_BIAS+env->regwptr[UREG_I6]))->ins[6])));
|
||||
err |= get_user(i7,
|
||||
(&(((struct target_reg_window *)(TARGET_STACK_BIAS+env->regwptr[UREG_I6]))->ins[7])));
|
||||
err |= put_user(fp, &(mcp->mc_fp));
|
||||
err |= put_user(i7, &(mcp->mc_i7));
|
||||
err |= __get_user(fp,
|
||||
(&(((struct target_reg_window *)(TARGET_STACK_BIAS+env->regwptr[UREG_I6]))->ins[6])));
|
||||
err |= __get_user(i7,
|
||||
(&(((struct target_reg_window *)(TARGET_STACK_BIAS+env->regwptr[UREG_I6]))->ins[7])));
|
||||
err |= __put_user(fp, &(mcp->mc_fp));
|
||||
err |= __put_user(i7, &(mcp->mc_i7));
|
||||
|
||||
src = &env->fpr;
|
||||
dst = &(ucp->uc_mcontext.mc_fpregs.mcfpu_fregs);
|
||||
for (i = 0; i < 64; i++, dst++, src++)
|
||||
err |= put_user(src, dst);
|
||||
err |= put_user(env->fsr, &(mcp->mc_fpregs.mcfpu_fsr));
|
||||
err |= put_user(env->gsr, &(mcp->mc_fpregs.mcfpu_gsr));
|
||||
err |= put_user(env->fprs, &(mcp->mc_fpregs.mcfpu_fprs));
|
||||
err |= __put_user(src, dst);
|
||||
err |= __put_user(env->fsr, &(mcp->mc_fpregs.mcfpu_fsr));
|
||||
err |= __put_user(env->gsr, &(mcp->mc_fpregs.mcfpu_gsr));
|
||||
err |= __put_user(env->fprs, &(mcp->mc_fpregs.mcfpu_fprs));
|
||||
|
||||
if (err)
|
||||
goto do_sigsegv;
|
||||
@ -2191,7 +2218,7 @@ restore_sigcontext(CPUState *regs, struct target_sigcontext *sc)
|
||||
/*
|
||||
* Determine which stack to use..
|
||||
*/
|
||||
static inline void *
|
||||
static inline abi_ulong
|
||||
get_sigframe(struct emulated_sigaction *ka, CPUState *regs, size_t frame_size)
|
||||
{
|
||||
unsigned long sp;
|
||||
@ -2211,17 +2238,19 @@ get_sigframe(struct emulated_sigaction *ka, CPUState *regs, size_t frame_size)
|
||||
sp = target_sigaltstack_used.ss_sp + target_sigaltstack_used.ss_size;
|
||||
}
|
||||
|
||||
return g2h((sp - frame_size) & ~7);
|
||||
return (sp - frame_size) & ~7;
|
||||
}
|
||||
|
||||
/* compare linux/arch/mips/kernel/signal.c:setup_frame() */
|
||||
static void setup_frame(int sig, struct emulated_sigaction * ka,
|
||||
target_sigset_t *set, CPUState *regs)
|
||||
target_sigset_t *set, CPUState *regs)
|
||||
{
|
||||
struct sigframe *frame;
|
||||
abi_ulong frame_addr;
|
||||
int i;
|
||||
|
||||
frame = get_sigframe(ka, regs, sizeof(*frame));
|
||||
if (!access_ok(VERIFY_WRITE, frame, sizeof (*frame)))
|
||||
frame_addr = get_sigframe(ka, regs, sizeof(*frame));
|
||||
if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0))
|
||||
goto give_sigsegv;
|
||||
|
||||
install_sigtramp(frame->sf_code, TARGET_NR_sigreturn);
|
||||
@ -2253,9 +2282,11 @@ static void setup_frame(int sig, struct emulated_sigaction * ka,
|
||||
* since it returns to userland using eret
|
||||
* we cannot do this here, and we must set PC directly */
|
||||
regs->PC[regs->current_tc] = regs->gpr[25][regs->current_tc] = ka->sa._sa_handler;
|
||||
unlock_user_struct(frame, frame_addr, 1);
|
||||
return;
|
||||
|
||||
give_sigsegv:
|
||||
unlock_user_struct(frame, frame_addr, 1);
|
||||
force_sig(TARGET_SIGSEGV/*, current*/);
|
||||
return;
|
||||
}
|
||||
@ -2263,6 +2294,7 @@ give_sigsegv:
|
||||
long do_sigreturn(CPUState *regs)
|
||||
{
|
||||
struct sigframe *frame;
|
||||
abi_ulong frame_addr;
|
||||
sigset_t blocked;
|
||||
target_sigset_t target_set;
|
||||
int i;
|
||||
@ -2270,8 +2302,8 @@ long do_sigreturn(CPUState *regs)
|
||||
#if defined(DEBUG_SIGNAL)
|
||||
fprintf(stderr, "do_sigreturn\n");
|
||||
#endif
|
||||
frame = (struct sigframe *) regs->gpr[29][regs->current_tc];
|
||||
if (!access_ok(VERIFY_READ, frame, sizeof(*frame)))
|
||||
frame_addr = regs->gpr[29][regs->current_tc];
|
||||
if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1))
|
||||
goto badframe;
|
||||
|
||||
for(i = 0; i < TARGET_NSIG_WORDS; i++) {
|
||||
|
@ -81,14 +81,18 @@ print_fdset(int n, target_ulong target_fds_addr)
|
||||
|
||||
gemu_log("[");
|
||||
if( target_fds_addr ) {
|
||||
target_long *target_fds;
|
||||
abi_long *target_fds;
|
||||
|
||||
if (!access_ok(VERIFY_READ, target_fds_addr, sizeof(*target_fds)*(n / TARGET_LONG_BITS + 1)))
|
||||
target_fds = lock_user(VERIFY_READ,
|
||||
target_fds_addr,
|
||||
sizeof(*target_fds)*(n / TARGET_ABI_BITS + 1),
|
||||
1);
|
||||
|
||||
if (!target_fds)
|
||||
return;
|
||||
|
||||
target_fds = lock_user(target_fds_addr, sizeof(*target_fds)*(n / TARGET_LONG_BITS + 1), 1);
|
||||
for (i=n; i>=0; i--) {
|
||||
if ((tswapl(target_fds[i / TARGET_LONG_BITS]) >> (i & (TARGET_LONG_BITS - 1))) & 1)
|
||||
if ((tswapl(target_fds[i / TARGET_ABI_BITS]) >> (i & (TARGET_ABI_BITS - 1))) & 1)
|
||||
gemu_log("%d,", i );
|
||||
}
|
||||
unlock_user(target_fds, target_fds_addr, 0);
|
||||
@ -102,10 +106,9 @@ print_timeval(target_ulong tv_addr)
|
||||
if( tv_addr ) {
|
||||
struct target_timeval *tv;
|
||||
|
||||
if (!access_ok(VERIFY_READ, tv_addr, sizeof(*tv)))
|
||||
tv = lock_user(VERIFY_READ, tv_addr, sizeof(*tv), 1);
|
||||
if (!tv)
|
||||
return;
|
||||
|
||||
tv = lock_user(tv_addr, sizeof(*tv), 1);
|
||||
gemu_log("{" TARGET_ABI_FMT_ld "," TARGET_ABI_FMT_ld "}",
|
||||
tv->tv_sec, tv->tv_usec);
|
||||
unlock_user(tv, tv_addr, 0);
|
||||
@ -165,27 +168,25 @@ print_execve(struct syscallname *name,
|
||||
target_ulong arg_ptr_addr;
|
||||
char *s;
|
||||
|
||||
if (!access_ok(VERIFY_READ, arg1, 1))
|
||||
if (!(s = lock_user_string(arg1)))
|
||||
return;
|
||||
|
||||
s = lock_user_string(arg1);
|
||||
gemu_log("%s(\"%s\",{", name->name, s);
|
||||
unlock_user(s, arg1, 0);
|
||||
|
||||
for (arg_ptr_addr = arg2; ; arg_ptr_addr += sizeof(target_ulong)) {
|
||||
target_ulong *arg_ptr, arg_addr, s_addr;
|
||||
|
||||
if (!access_ok(VERIFY_READ, arg_ptr_addr, sizeof(target_ulong)))
|
||||
arg_ptr = lock_user(VERIFY_READ, arg_ptr_addr, sizeof(target_ulong), 1);
|
||||
if (!arg_ptr)
|
||||
return;
|
||||
|
||||
arg_ptr = lock_user(arg_ptr_addr, sizeof(target_ulong), 1);
|
||||
arg_addr = tswapl(*arg_ptr);
|
||||
unlock_user(arg_ptr, arg_ptr_addr, 0);
|
||||
if (!arg_addr)
|
||||
break;
|
||||
s = lock_user_string(arg_addr);
|
||||
gemu_log("\"%s\",", s);
|
||||
unlock_user(s, s_addr, 0);
|
||||
if ((s = lock_user_string(arg_addr))) {
|
||||
gemu_log("\"%s\",", s);
|
||||
unlock_user(s, s_addr, 0);
|
||||
}
|
||||
}
|
||||
|
||||
gemu_log("NULL})");
|
||||
|
File diff suppressed because it is too large
Load Diff
51
linux-user/uaccess.c
Normal file
51
linux-user/uaccess.c
Normal file
@ -0,0 +1,51 @@
|
||||
/* User memory access */
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "qemu.h"
|
||||
|
||||
/* copy_from_user() and copy_to_user() are usually used to copy data
|
||||
* buffers between the target and host. These internally perform
|
||||
* locking/unlocking of the memory.
|
||||
*/
|
||||
abi_long copy_from_user(void *hptr, abi_ulong gaddr, size_t len)
|
||||
{
|
||||
abi_long ret = 0;
|
||||
void *ghptr;
|
||||
|
||||
if ((ghptr = lock_user(VERIFY_READ, gaddr, len, 1))) {
|
||||
memcpy(hptr, ghptr, len);
|
||||
unlock_user(ghptr, gaddr, 0);
|
||||
} else
|
||||
ret = -TARGET_EFAULT;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
abi_long copy_to_user(abi_ulong gaddr, void *hptr, size_t len)
|
||||
{
|
||||
abi_long ret = 0;
|
||||
void *ghptr;
|
||||
|
||||
if ((ghptr = lock_user(VERIFY_WRITE, gaddr, len, 0))) {
|
||||
memcpy(ghptr, hptr, len);
|
||||
unlock_user(ghptr, gaddr, len);
|
||||
} else
|
||||
ret = -TARGET_EFAULT;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
/* Return the length of a string in target memory. */
|
||||
/* FIXME - this doesn't check access_ok() - it's rather complicated to
|
||||
* do it correctly because we need to check the bytes in a page and then
|
||||
* skip to the next page and check the bytes there until we find the
|
||||
* terminator. There should be a general function to do this that
|
||||
* can look for any byte terminator in a buffer - not strlen().
|
||||
*/
|
||||
abi_long target_strlen(abi_ulong gaddr)
|
||||
{
|
||||
return strlen(g2h(gaddr));
|
||||
}
|
@ -64,7 +64,9 @@ void save_v86_state(CPUX86State *env)
|
||||
TaskState *ts = env->opaque;
|
||||
struct target_vm86plus_struct * target_v86;
|
||||
|
||||
lock_user_struct(target_v86, ts->target_v86, 0);
|
||||
if (!lock_user_struct(VERIFY_WRITE, target_v86, ts->target_v86, 0))
|
||||
/* FIXME - should return an error */
|
||||
return;
|
||||
/* put the VM86 registers in the userspace register structure */
|
||||
target_v86->regs.eax = tswap32(env->regs[R_EAX]);
|
||||
target_v86->regs.ebx = tswap32(env->regs[R_EBX]);
|
||||
@ -424,7 +426,8 @@ int do_vm86(CPUX86State *env, long subfunction, abi_ulong vm86_addr)
|
||||
ts->vm86_saved_regs.gs = env->segs[R_GS].selector;
|
||||
|
||||
ts->target_v86 = vm86_addr;
|
||||
lock_user_struct(target_v86, vm86_addr, 1);
|
||||
if (!lock_user_struct(VERIFY_READ, target_v86, vm86_addr, 1))
|
||||
return -EFAULT;
|
||||
/* build vm86 CPU state */
|
||||
ts->v86flags = tswap32(target_v86->regs.eflags);
|
||||
env->eflags = (env->eflags & ~SAFE_MASK) |
|
||||
|
84
m68k-semi.c
84
m68k-semi.c
@ -107,7 +107,9 @@ static void translate_stat(CPUState *env, target_ulong addr, struct stat *s)
|
||||
{
|
||||
struct m68k_gdb_stat *p;
|
||||
|
||||
p = lock_user(addr, sizeof(struct m68k_gdb_stat), 0);
|
||||
if (!(p = lock_user(VERIFY_WRITE, addr, sizeof(struct m68k_gdb_stat), 0)))
|
||||
/* FIXME - should this return an error code? */
|
||||
return;
|
||||
p->gdb_st_dev = cpu_to_be32(s->st_dev);
|
||||
p->gdb_st_ino = cpu_to_be32(s->st_ino);
|
||||
p->gdb_st_mode = cpu_to_be32(s->st_mode);
|
||||
@ -168,9 +170,13 @@ void do_m68k_semihosting(CPUM68KState *env, int nr)
|
||||
ARG(2), ARG(3));
|
||||
return;
|
||||
} else {
|
||||
p = lock_user_string(ARG(0));
|
||||
result = open(p, translate_openflags(ARG(2)), ARG(3));
|
||||
unlock_user(p, ARG(0), 0);
|
||||
if (!(p = lock_user_string(ARG(0)))) {
|
||||
/* FIXME - check error code? */
|
||||
result = -1;
|
||||
} else {
|
||||
result = open(p, translate_openflags(ARG(2)), ARG(3));
|
||||
unlock_user(p, ARG(0), 0);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case HOSTED_CLOSE:
|
||||
@ -196,9 +202,13 @@ void do_m68k_semihosting(CPUM68KState *env, int nr)
|
||||
ARG(0), ARG(1), len);
|
||||
return;
|
||||
} else {
|
||||
p = lock_user(ARG(1), len, 0);
|
||||
result = read(ARG(0), p, len);
|
||||
unlock_user(p, ARG(1), len);
|
||||
if (!(p = lock_user(VERIFY_WRITE, ARG(1), len, 0))) {
|
||||
/* FIXME - check error code? */
|
||||
result = -1;
|
||||
} else {
|
||||
result = read(ARG(0), p, len);
|
||||
unlock_user(p, ARG(1), len);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case HOSTED_WRITE:
|
||||
@ -208,9 +218,13 @@ void do_m68k_semihosting(CPUM68KState *env, int nr)
|
||||
ARG(0), ARG(1), len);
|
||||
return;
|
||||
} else {
|
||||
p = lock_user(ARG(1), len, 1);
|
||||
result = write(ARG(0), p, len);
|
||||
unlock_user(p, ARG(0), 0);
|
||||
if (!(p = lock_user(VERIFY_READ, ARG(1), len, 1))) {
|
||||
/* FIXME - check error code? */
|
||||
result = -1;
|
||||
} else {
|
||||
result = write(ARG(0), p, len);
|
||||
unlock_user(p, ARG(0), 0);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case HOSTED_LSEEK:
|
||||
@ -237,7 +251,12 @@ void do_m68k_semihosting(CPUM68KState *env, int nr)
|
||||
} else {
|
||||
p = lock_user_string(ARG(0));
|
||||
q = lock_user_string(ARG(2));
|
||||
result = rename(p, q);
|
||||
if (!p || !q) {
|
||||
/* FIXME - check error code? */
|
||||
result = -1;
|
||||
} else {
|
||||
result = rename(p, q);
|
||||
}
|
||||
unlock_user(p, ARG(0), 0);
|
||||
unlock_user(q, ARG(2), 0);
|
||||
}
|
||||
@ -248,9 +267,13 @@ void do_m68k_semihosting(CPUM68KState *env, int nr)
|
||||
ARG(0), (int)ARG(1));
|
||||
return;
|
||||
} else {
|
||||
p = lock_user_string(ARG(0));
|
||||
result = unlink(p);
|
||||
unlock_user(p, ARG(0), 0);
|
||||
if (!(p = lock_user_string(ARG(0)))) {
|
||||
/* FIXME - check error code? */
|
||||
result = -1;
|
||||
} else {
|
||||
result = unlink(p);
|
||||
unlock_user(p, ARG(0), 0);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case HOSTED_STAT:
|
||||
@ -260,9 +283,13 @@ void do_m68k_semihosting(CPUM68KState *env, int nr)
|
||||
return;
|
||||
} else {
|
||||
struct stat s;
|
||||
p = lock_user_string(ARG(0));
|
||||
result = stat(p, &s);
|
||||
unlock_user(p, ARG(0), 0);
|
||||
if (!(p = lock_user_string(ARG(0)))) {
|
||||
/* FIXME - check error code? */
|
||||
result = -1;
|
||||
} else {
|
||||
result = stat(p, &s);
|
||||
unlock_user(p, ARG(0), 0);
|
||||
}
|
||||
if (result == 0) {
|
||||
translate_stat(env, ARG(2), &s);
|
||||
}
|
||||
@ -291,10 +318,15 @@ void do_m68k_semihosting(CPUM68KState *env, int nr)
|
||||
struct gdb_timeval *p;
|
||||
result = qemu_gettimeofday(&tv);
|
||||
if (result != 0) {
|
||||
p = lock_user(ARG(0), sizeof(struct gdb_timeval), 0);
|
||||
p->tv_sec = cpu_to_be32(tv.tv_sec);
|
||||
p->tv_usec = cpu_to_be64(tv.tv_usec);
|
||||
unlock_user(p, ARG(0), sizeof(struct gdb_timeval));
|
||||
if (!(p = lock_user(VERIFY_WRITE,
|
||||
ARG(0), sizeof(struct gdb_timeval), 0))) {
|
||||
/* FIXME - check error code? */
|
||||
result = -1;
|
||||
} else {
|
||||
p->tv_sec = cpu_to_be32(tv.tv_sec);
|
||||
p->tv_usec = cpu_to_be64(tv.tv_usec);
|
||||
unlock_user(p, ARG(0), sizeof(struct gdb_timeval));
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
@ -312,9 +344,13 @@ void do_m68k_semihosting(CPUM68KState *env, int nr)
|
||||
ARG(0), (int)ARG(1));
|
||||
return;
|
||||
} else {
|
||||
p = lock_user_string(ARG(0));
|
||||
result = system(p);
|
||||
unlock_user(p, ARG(0), 0);
|
||||
if (!(p = lock_user_string(ARG(0)))) {
|
||||
/* FIXME - check error code? */
|
||||
result = -1;
|
||||
} else {
|
||||
result = system(p);
|
||||
unlock_user(p, ARG(0), 0);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case HOSTED_INIT_SIM:
|
||||
|
@ -41,7 +41,7 @@ static void *softmmu_lock_user(CPUState *env, uint32_t addr, uint32_t len,
|
||||
cpu_memory_rw_debug(env, addr, p, len, 0);
|
||||
return p;
|
||||
}
|
||||
#define lock_user(p, len, copy) softmmu_lock_user(env, p, len, copy)
|
||||
#define lock_user(type, p, len, copy) softmmu_lock_user(env, p, len, copy)
|
||||
static char *softmmu_lock_user_string(CPUState *env, uint32_t addr)
|
||||
{
|
||||
char *p;
|
||||
|
Loading…
Reference in New Issue
Block a user