aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorbellard <bellard@c046a42c-6fe2-441c-8c8c-71466251a162>2004-02-22 13:40:13 +0000
committerbellard <bellard@c046a42c-6fe2-441c-8c8c-71466251a162>2004-02-22 13:40:13 +0000
commitedf779ffccc836661a7b654d320571a6c220caea (patch)
treea2da1f139f832957716890525c94f105dc46713c
parent121061dcdfdf5ef1d78cd2ae84b39b779a568e28 (diff)
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
-rw-r--r--linux-user/elfload.c43
-rw-r--r--linux-user/qemu.h118
-rw-r--r--linux-user/signal.c72
-rw-r--r--linux-user/syscall.c21
4 files changed, 142 insertions, 112 deletions
diff --git a/linux-user/elfload.c b/linux-user/elfload.c
index 71055255c3..980ab6ba06 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 1a3ad6274a..be95ff9183 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 666d6e14fb..41affb56e7 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 9ac95729f5..6fae50dd01 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)