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:
bellard 2007-11-11 14:26:47 +00:00
parent 44f8625d23
commit 579a97f7ff
14 changed files with 973 additions and 624 deletions

View file

@ -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

View file

@ -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
View file

@ -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);
}

View file

@ -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);
}
/*

View file

@ -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;

View file

@ -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)

View file

@ -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)

View file

@ -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++) {

View file

@ -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
View 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));
}

View file

@ -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) |

View file

@ -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:

View file

@ -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;