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
This commit is contained in:
parent
121061dcdf
commit
edf779ffcc
@ -263,19 +263,11 @@ struct exec
|
|||||||
|
|
||||||
#define DLINFO_ITEMS 11
|
#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)
|
static inline void memcpy_fromfs(void * to, const void * from, unsigned long n)
|
||||||
{
|
{
|
||||||
memcpy(to, from, 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;
|
extern unsigned long x86_stack_size;
|
||||||
|
|
||||||
static int load_aout_interp(void * exptr, int interp_fd);
|
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 */
|
return 0; /* bullet-proofing */
|
||||||
}
|
}
|
||||||
while (argc-- > 0) {
|
while (argc-- > 0) {
|
||||||
if (!(tmp1 = tmp = get_user(argv+argc))) {
|
tmp = argv[argc];
|
||||||
|
if (!tmp) {
|
||||||
fprintf(stderr, "VFS: argc is wrong");
|
fprintf(stderr, "VFS: argc is wrong");
|
||||||
exit(-1);
|
exit(-1);
|
||||||
}
|
}
|
||||||
while (get_user(tmp++));
|
tmp1 = tmp;
|
||||||
|
while (*tmp++);
|
||||||
len = tmp - tmp1;
|
len = tmp - tmp1;
|
||||||
if (p < len) { /* this shouldn't happen - 128kB */
|
if (p < len) { /* this shouldn't happen - 128kB */
|
||||||
return 0;
|
return 0;
|
||||||
@ -395,7 +389,7 @@ static unsigned long copy_strings(int argc,char ** argv,unsigned long *page,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (len == 0 || offset == 0) {
|
if (len == 0 || offset == 0) {
|
||||||
*(pag + offset) = get_user(tmp);
|
*(pag + offset) = *tmp;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
int bytes_to_copy = (len > offset) ? offset : len;
|
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 *argv, *envp;
|
||||||
target_ulong *sp, *csp;
|
target_ulong *sp, *csp;
|
||||||
|
int v;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Force 16 byte _final_ alignment here for generality.
|
* 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);
|
sp -= ((unsigned long)csp & 15UL) / sizeof(*sp);
|
||||||
|
|
||||||
#define NEW_AUX_ENT(nr, id, val) \
|
#define NEW_AUX_ENT(nr, id, val) \
|
||||||
put_user (tswapl(id), sp + (nr * 2)); \
|
put_user (id, sp + (nr * 2)); \
|
||||||
put_user (tswapl(val), sp + (nr * 2 + 1))
|
put_user (val, sp + (nr * 2 + 1))
|
||||||
sp -= 2;
|
sp -= 2;
|
||||||
NEW_AUX_ENT (0, AT_NULL, 0);
|
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;
|
sp -= argc+1;
|
||||||
argv = sp;
|
argv = sp;
|
||||||
if (!ibcs) {
|
if (!ibcs) {
|
||||||
put_user(tswapl((target_ulong)envp),--sp);
|
put_user((target_ulong)envp,--sp);
|
||||||
put_user(tswapl((target_ulong)argv),--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);
|
info->arg_start = (unsigned int)((unsigned long)p & 0xffffffff);
|
||||||
while (argc-->0) {
|
while (argc-->0) {
|
||||||
put_user(tswapl((target_ulong)p),argv++);
|
put_user((target_ulong)p,argv++);
|
||||||
while (get_user(p++)) /* nothing */ ;
|
do {
|
||||||
|
get_user(v, p);
|
||||||
|
p++;
|
||||||
|
} while (v != 0);
|
||||||
}
|
}
|
||||||
put_user(0,argv);
|
put_user(0,argv);
|
||||||
info->arg_end = info->env_start = (unsigned int)((unsigned long)p & 0xffffffff);
|
info->arg_end = info->env_start = (unsigned int)((unsigned long)p & 0xffffffff);
|
||||||
while (envc-->0) {
|
while (envc-->0) {
|
||||||
put_user(tswapl((target_ulong)p),envp++);
|
put_user((target_ulong)p,envp++);
|
||||||
while (get_user(p++)) /* nothing */ ;
|
do {
|
||||||
|
get_user(v, p);
|
||||||
|
p++;
|
||||||
|
} while (v != 0);
|
||||||
}
|
}
|
||||||
put_user(0,envp);
|
put_user(0,envp);
|
||||||
info->env_end = (unsigned int)((unsigned long)p & 0xffffffff);
|
info->env_end = (unsigned int)((unsigned long)p & 0xffffffff);
|
||||||
|
@ -4,6 +4,7 @@
|
|||||||
#include "thunk.h"
|
#include "thunk.h"
|
||||||
|
|
||||||
#include <signal.h>
|
#include <signal.h>
|
||||||
|
#include <string.h>
|
||||||
#include "syscall_defs.h"
|
#include "syscall_defs.h"
|
||||||
|
|
||||||
#include "cpu.h"
|
#include "cpu.h"
|
||||||
@ -120,4 +121,121 @@ long target_mremap(unsigned long old_addr, unsigned long old_size,
|
|||||||
unsigned long new_addr);
|
unsigned long new_addr);
|
||||||
int target_msync(unsigned long start, unsigned long len, int flags);
|
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
|
#endif
|
||||||
|
@ -450,69 +450,6 @@ int do_sigaction(int sig, const struct target_sigaction *act,
|
|||||||
return 0;
|
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
|
#ifndef offsetof
|
||||||
#define offsetof(type, field) ((size_t) &((type *)0)->field)
|
#define offsetof(type, field) ((size_t) &((type *)0)->field)
|
||||||
#endif
|
#endif
|
||||||
@ -707,10 +644,8 @@ static void setup_frame(int sig, struct emulated_sigaction *ka,
|
|||||||
|
|
||||||
frame = get_sigframe(ka, env, sizeof(*frame));
|
frame = get_sigframe(ka, env, sizeof(*frame));
|
||||||
|
|
||||||
#if 0
|
|
||||||
if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame)))
|
if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame)))
|
||||||
goto give_sigsegv;
|
goto give_sigsegv;
|
||||||
#endif
|
|
||||||
err |= __put_user((/*current->exec_domain
|
err |= __put_user((/*current->exec_domain
|
||||||
&& current->exec_domain->signal_invmap
|
&& current->exec_domain->signal_invmap
|
||||||
&& sig < 32
|
&& sig < 32
|
||||||
@ -773,10 +708,8 @@ static void setup_rt_frame(int sig, struct emulated_sigaction *ka,
|
|||||||
|
|
||||||
frame = get_sigframe(ka, env, sizeof(*frame));
|
frame = get_sigframe(ka, env, sizeof(*frame));
|
||||||
|
|
||||||
#if 0
|
|
||||||
if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame)))
|
if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame)))
|
||||||
goto give_sigsegv;
|
goto give_sigsegv;
|
||||||
#endif
|
|
||||||
|
|
||||||
err |= __put_user((/*current->exec_domain
|
err |= __put_user((/*current->exec_domain
|
||||||
&& current->exec_domain->signal_invmap
|
&& 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));
|
struct rt_sigframe *frame = get_sigframe(ka, env, sizeof(*frame));
|
||||||
int err = 0;
|
int err = 0;
|
||||||
|
|
||||||
#if 0
|
|
||||||
if (!access_ok(VERIFY_WRITE, frame, sizeof (*frame)))
|
if (!access_ok(VERIFY_WRITE, frame, sizeof (*frame)))
|
||||||
return 1;
|
return /* 1 */;
|
||||||
#endif
|
|
||||||
__put_user_error(&frame->info, (target_ulong *)&frame->pinfo, err);
|
__put_user_error(&frame->info, (target_ulong *)&frame->pinfo, err);
|
||||||
__put_user_error(&frame->uc, (target_ulong *)&frame->puc, err);
|
__put_user_error(&frame->uc, (target_ulong *)&frame->puc, err);
|
||||||
err |= copy_siginfo_to_user(&frame->info, info);
|
err |= copy_siginfo_to_user(&frame->info, info);
|
||||||
|
@ -239,27 +239,6 @@ extern int setresgid(gid_t, gid_t, gid_t);
|
|||||||
extern int getresgid(gid_t *, gid_t *, gid_t *);
|
extern int getresgid(gid_t *, gid_t *, gid_t *);
|
||||||
extern int setgroups(int, 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)
|
static inline long get_errno(long ret)
|
||||||
{
|
{
|
||||||
if (ret == -1)
|
if (ret == -1)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user