diff options
author | bellard <bellard@c046a42c-6fe2-441c-8c8c-71466251a162> | 2004-02-22 13:40:13 +0000 |
---|---|---|
committer | bellard <bellard@c046a42c-6fe2-441c-8c8c-71466251a162> | 2004-02-22 13:40:13 +0000 |
commit | edf779ffccc836661a7b654d320571a6c220caea (patch) | |
tree | a2da1f139f832957716890525c94f105dc46713c /linux-user | |
parent | 121061dcdfdf5ef1d78cd2ae84b39b779a568e28 (diff) | |
download | qemu-edf779ffccc836661a7b654d320571a6c220caea.zip qemu-edf779ffccc836661a7b654d320571a6c220caea.tar.gz qemu-edf779ffccc836661a7b654d320571a6c220caea.tar.bz2 |
use kernel like macros for user access (will be useful someday to have a better error checking
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@634 c046a42c-6fe2-441c-8c8c-71466251a162
Diffstat (limited to 'linux-user')
-rw-r--r-- | linux-user/elfload.c | 43 | ||||
-rw-r--r-- | linux-user/qemu.h | 118 | ||||
-rw-r--r-- | linux-user/signal.c | 72 | ||||
-rw-r--r-- | linux-user/syscall.c | 21 |
4 files changed, 142 insertions, 112 deletions
diff --git a/linux-user/elfload.c b/linux-user/elfload.c index 7105525..980ab6b 100644 --- a/linux-user/elfload.c +++ b/linux-user/elfload.c @@ -263,19 +263,11 @@ struct exec #define DLINFO_ITEMS 11 -#define put_user(x,ptr) (void)(*(ptr) = (typeof(*ptr))(x)) -#define get_user(ptr) (typeof(*ptr))(*(ptr)) - static inline void memcpy_fromfs(void * to, const void * from, unsigned long n) { memcpy(to, from, n); } -static inline void memcpy_tofs(void * to, const void * from, unsigned long n) -{ - memcpy(to, from, n); -} - extern unsigned long x86_stack_size; static int load_aout_interp(void * exptr, int interp_fd); @@ -373,11 +365,13 @@ static unsigned long copy_strings(int argc,char ** argv,unsigned long *page, return 0; /* bullet-proofing */ } while (argc-- > 0) { - if (!(tmp1 = tmp = get_user(argv+argc))) { + tmp = argv[argc]; + if (!tmp) { fprintf(stderr, "VFS: argc is wrong"); exit(-1); } - while (get_user(tmp++)); + tmp1 = tmp; + while (*tmp++); len = tmp - tmp1; if (p < len) { /* this shouldn't happen - 128kB */ return 0; @@ -395,7 +389,7 @@ static unsigned long copy_strings(int argc,char ** argv,unsigned long *page, } } if (len == 0 || offset == 0) { - *(pag + offset) = get_user(tmp); + *(pag + offset) = *tmp; } else { int bytes_to_copy = (len > offset) ? offset : len; @@ -599,7 +593,8 @@ static unsigned int * create_elf_tables(char *p, int argc, int envc, { target_ulong *argv, *envp; target_ulong *sp, *csp; - + int v; + /* * Force 16 byte _final_ alignment here for generality. */ @@ -616,8 +611,8 @@ static unsigned int * create_elf_tables(char *p, int argc, int envc, sp -= ((unsigned long)csp & 15UL) / sizeof(*sp); #define NEW_AUX_ENT(nr, id, val) \ - put_user (tswapl(id), sp + (nr * 2)); \ - put_user (tswapl(val), sp + (nr * 2 + 1)) + put_user (id, sp + (nr * 2)); \ + put_user (val, sp + (nr * 2 + 1)) sp -= 2; NEW_AUX_ENT (0, AT_NULL, 0); @@ -647,20 +642,26 @@ static unsigned int * create_elf_tables(char *p, int argc, int envc, sp -= argc+1; argv = sp; if (!ibcs) { - put_user(tswapl((target_ulong)envp),--sp); - put_user(tswapl((target_ulong)argv),--sp); + put_user((target_ulong)envp,--sp); + put_user((target_ulong)argv,--sp); } - put_user(tswapl(argc),--sp); + put_user(argc,--sp); info->arg_start = (unsigned int)((unsigned long)p & 0xffffffff); while (argc-->0) { - put_user(tswapl((target_ulong)p),argv++); - while (get_user(p++)) /* nothing */ ; + put_user((target_ulong)p,argv++); + do { + get_user(v, p); + p++; + } while (v != 0); } put_user(0,argv); info->arg_end = info->env_start = (unsigned int)((unsigned long)p & 0xffffffff); while (envc-->0) { - put_user(tswapl((target_ulong)p),envp++); - while (get_user(p++)) /* nothing */ ; + put_user((target_ulong)p,envp++); + do { + get_user(v, p); + p++; + } while (v != 0); } put_user(0,envp); info->env_end = (unsigned int)((unsigned long)p & 0xffffffff); diff --git a/linux-user/qemu.h b/linux-user/qemu.h index 1a3ad62..be95ff9 100644 --- a/linux-user/qemu.h +++ b/linux-user/qemu.h @@ -4,6 +4,7 @@ #include "thunk.h" #include <signal.h> +#include <string.h> #include "syscall_defs.h" #include "cpu.h" @@ -120,4 +121,121 @@ long target_mremap(unsigned long old_addr, unsigned long old_size, unsigned long new_addr); int target_msync(unsigned long start, unsigned long len, int flags); +/* user access */ + +#define VERIFY_READ 0 +#define VERIFY_WRITE 1 + +#define access_ok(type,addr,size) (1) + +#define __put_user(x,ptr)\ +({\ + int size = sizeof(*ptr);\ + switch(size) {\ + case 1:\ + stb(ptr, (typeof(*ptr))(x));\ + break;\ + case 2:\ + stw(ptr, (typeof(*ptr))(x));\ + break;\ + case 4:\ + stl(ptr, (typeof(*ptr))(x));\ + break;\ + case 8:\ + stq(ptr, (typeof(*ptr))(x));\ + break;\ + default:\ + abort();\ + }\ + 0;\ +}) + +#define __get_user(x, ptr) \ +({\ + int size = sizeof(*ptr);\ + switch(size) {\ + case 1:\ + x = (typeof(*ptr))ldub(ptr);\ + break;\ + case 2:\ + x = (typeof(*ptr))lduw(ptr);\ + break;\ + case 4:\ + x = (typeof(*ptr))ldl(ptr);\ + break;\ + case 8:\ + x = (typeof(*ptr))ldq(ptr);\ + break;\ + default:\ + abort();\ + }\ + 0;\ +}) + +static inline unsigned long __copy_to_user(void *dst, const void *src, + unsigned long size) +{ + memcpy(dst, src, size); + return 0; +} + +static inline unsigned long __copy_from_user(void *dst, const void *src, + unsigned long size) +{ + memcpy(dst, src, size); + return 0; +} + +static inline unsigned long __clear_user(void *dst, unsigned long size) +{ + memset(dst, 0, size); + return 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;\ +}) + +#define get_user(x,ptr)\ +({\ + int __ret;\ + if (access_ok(VERIFY_READ, ptr, sizeof(*ptr)))\ + __ret = __get_user(x, ptr);\ + else\ + __ret = -EFAULT;\ + __ret;\ +}) + +static inline unsigned long copy_to_user(void *dst, const void *src, + unsigned long size) +{ + if (access_ok(VERIFY_WRITE, dst, size)) + return __copy_to_user(dst, src, size); + else + return size; +} + +static inline unsigned long copy_from_user(void *dst, const void *src, + unsigned long size) +{ + if (access_ok(VERIFY_READ, src, size)) + return __copy_from_user(dst, src, size); + else + return size; +} + +static inline unsigned long clear_user(void *dst, unsigned long size) +{ + if (access_ok(VERIFY_WRITE, dst, size)) + return __clear_user(dst, size); + else + return size; +} + #endif diff --git a/linux-user/signal.c b/linux-user/signal.c index 666d6e1..41affb5 100644 --- a/linux-user/signal.c +++ b/linux-user/signal.c @@ -450,69 +450,6 @@ int do_sigaction(int sig, const struct target_sigaction *act, return 0; } -#define __put_user(x,ptr)\ -({\ - int size = sizeof(*ptr);\ - switch(size) {\ - case 1:\ - stb(ptr, (typeof(*ptr))(x));\ - break;\ - case 2:\ - stw(ptr, (typeof(*ptr))(x));\ - break;\ - case 4:\ - stl(ptr, (typeof(*ptr))(x));\ - break;\ - case 8:\ - stq(ptr, (typeof(*ptr))(x));\ - break;\ - default:\ - abort();\ - }\ - 0;\ -}) - -#define __get_user(x, ptr) \ -({\ - int size = sizeof(*ptr);\ - switch(size) {\ - case 1:\ - x = (typeof(*ptr))ldub(ptr);\ - break;\ - case 2:\ - x = (typeof(*ptr))lduw(ptr);\ - break;\ - case 4:\ - x = (typeof(*ptr))ldl(ptr);\ - break;\ - case 8:\ - x = (typeof(*ptr))ldq(ptr);\ - break;\ - default:\ - abort();\ - }\ - 0;\ -}) - - -#define __copy_to_user(dst, src, size)\ -({\ - memcpy(dst, src, size);\ - 0;\ -}) - -#define __copy_from_user(dst, src, size)\ -({\ - memcpy(dst, src, size);\ - 0;\ -}) - -#define __clear_user(dst, size)\ -({\ - memset(dst, 0, size);\ - 0;\ -}) - #ifndef offsetof #define offsetof(type, field) ((size_t) &((type *)0)->field) #endif @@ -707,10 +644,8 @@ static void setup_frame(int sig, struct emulated_sigaction *ka, frame = get_sigframe(ka, env, sizeof(*frame)); -#if 0 if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame))) goto give_sigsegv; -#endif err |= __put_user((/*current->exec_domain && current->exec_domain->signal_invmap && sig < 32 @@ -773,10 +708,8 @@ static void setup_rt_frame(int sig, struct emulated_sigaction *ka, frame = get_sigframe(ka, env, sizeof(*frame)); -#if 0 if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame))) goto give_sigsegv; -#endif err |= __put_user((/*current->exec_domain && current->exec_domain->signal_invmap @@ -1172,10 +1105,9 @@ static void setup_rt_frame(int usig, struct emulated_sigaction *ka, struct rt_sigframe *frame = get_sigframe(ka, env, sizeof(*frame)); int err = 0; -#if 0 if (!access_ok(VERIFY_WRITE, frame, sizeof (*frame))) - return 1; -#endif + return /* 1 */; + __put_user_error(&frame->info, (target_ulong *)&frame->pinfo, err); __put_user_error(&frame->uc, (target_ulong *)&frame->puc, err); err |= copy_siginfo_to_user(&frame->info, info); diff --git a/linux-user/syscall.c b/linux-user/syscall.c index 9ac9572..6fae50d 100644 --- a/linux-user/syscall.c +++ b/linux-user/syscall.c @@ -239,27 +239,6 @@ extern int setresgid(gid_t, gid_t, gid_t); extern int getresgid(gid_t *, gid_t *, gid_t *); extern int setgroups(int, gid_t *); -#define put_user(x,ptr)\ -({\ - int size = sizeof(*ptr);\ - switch(size) {\ - case 1:\ - stb(ptr, (typeof(*ptr))(x));\ - break;\ - case 2:\ - stw(ptr, (typeof(*ptr))(x));\ - break;\ - case 4:\ - stl(ptr, (typeof(*ptr))(x));\ - break;\ - case 8:\ - stq(ptr, (typeof(*ptr))(x));\ - break;\ - default:\ - abort();\ - }\ - 0;\ -}) static inline long get_errno(long ret) { if (ret == -1) |