From: Stuart Anderson <anderson@netsweng.com>
To: qemu-devel@nongnu.org
Subject: [Qemu-devel] [PATCH] EFAULT implmentation in linux-user
Date: Sun, 3 Jun 2007 20:47:45 -0400 (EDT) [thread overview]
Message-ID: <Pine.LNX.4.64.0706032039260.21792@trantor.stuart.netsweng.com> (raw)
[-- Attachment #1: Type: TEXT/PLAIN, Size: 1588 bytes --]
The attached patch implements EFAULT detection in linux-user. It is
suprising how much software "relies" on the kernel returning EFAULT
instead of just crashing.
This patch can be broken down into 3 parts:
exec.c:
Add page_check_range(), which uses the page map of the target to
determine wether an address and range are valid.EFAULT is
returned when an invalid address is detected.
linux-user/qemu.h:
Add lock_and_check_user_struct(), wich is similar to
lock_user_struct(), but adds a call to page_check_range()
to detect bad addresses. Once all occurrances of
lock_user_struct() have been converted over to this new function,
the new function could be renamed back to lock_user_struct() to
shorten it slightly.
linux-user/syscall.s:
This is where lock_and_check_user_struct() is used. It is used
to perform the mapping from target to host addresses. Generally,
calls to lock_user_struct() have been replaced with calls to
lock_and_check_user_struct(). For example
- lock_user_struct(target_tv, target_addr, 0);
+ if( (ret=lock_and_check_user_struct(&target_tv,target_addr,
sizeof(*target_tv),0,PAGE_WRITE)) != 0 ) return -ret;
These changes permit many of the tests in LTP for error conditions to
now pass.
Stuart
Stuart R. Anderson anderson@netsweng.com
Network & Software Engineering http://www.netsweng.com/
1024D/37A79149: 0791 D3B8 9A4C 2CDC A31F
BD03 0A62 E534 37A7 9149
[-- Attachment #2: EFAULT implementation --]
[-- Type: TEXT/x-diff, Size: 45204 bytes --]
Index: qemu/exec.c
===================================================================
--- qemu.orig/exec.c 2007-06-03 20:36:07.000000000 -0400
+++ qemu/exec.c 2007-06-03 20:36:27.000000000 -0400
@@ -1846,6 +1846,29 @@
spin_unlock(&tb_lock);
}
+int page_check_range(target_ulong start, target_ulong len, int flags)
+{
+ PageDesc *p;
+ target_ulong end;
+ target_ulong addr;
+
+ end = TARGET_PAGE_ALIGN(start+len); /* must do before we loose bits in the next step */
+ start = start & TARGET_PAGE_MASK;
+
+ if( end < start ) return EFAULT; /* we've wrapped around */
+ for(addr = start; addr < end; addr += TARGET_PAGE_SIZE) {
+ p = page_find(addr >> TARGET_PAGE_BITS);
+ if( !p ) return EFAULT;
+ if( !(p->flags & PAGE_VALID) ) return EFAULT;
+
+ if (!(p->flags & PAGE_READ) &&
+ (flags & PAGE_READ) ) return EFAULT;
+ if (!(p->flags & PAGE_WRITE) &&
+ (flags & PAGE_WRITE) ) return EFAULT;
+ }
+ return 0;
+}
+
/* called from signal handler: invalidate the code and unprotect the
page. Return TRUE if the fault was succesfully handled. */
int page_unprotect(target_ulong address, unsigned long pc, void *puc)
Index: qemu/cpu-all.h
===================================================================
--- qemu.orig/cpu-all.h 2007-06-03 20:36:07.000000000 -0400
+++ qemu/cpu-all.h 2007-06-03 20:36:27.000000000 -0400
@@ -691,6 +691,7 @@
int page_get_flags(target_ulong address);
void page_set_flags(target_ulong start, target_ulong end, int flags);
void page_unprotect_range(target_ulong data, target_ulong data_size);
+int page_check_range(target_ulong start, target_ulong len, int flags);
#define SINGLE_CPU_DEFINES
#ifdef SINGLE_CPU_DEFINES
Index: qemu/linux-user/syscall.c
===================================================================
--- qemu.orig/linux-user/syscall.c 2007-06-03 20:36:07.000000000 -0400
+++ qemu/linux-user/syscall.c 2007-06-03 20:37:36.000000000 -0400
@@ -402,12 +402,13 @@
#endif
}
-static inline void host_to_target_rusage(target_ulong target_addr,
+static inline long host_to_target_rusage(target_ulong target_addr,
const struct rusage *rusage)
{
+ long ret = 0;
struct target_rusage *target_rusage;
- lock_user_struct(target_rusage, target_addr, 0);
+ if( (ret=lock_and_check_user_struct(&target_rusage,target_addr,sizeof(*target_rusage),0,PAGE_WRITE)) != 0 ) return -ret;
target_rusage->ru_utime.tv_sec = tswapl(rusage->ru_utime.tv_sec);
target_rusage->ru_utime.tv_usec = tswapl(rusage->ru_utime.tv_usec);
target_rusage->ru_stime.tv_sec = tswapl(rusage->ru_stime.tv_sec);
@@ -429,23 +430,25 @@
unlock_user_struct(target_rusage, target_addr, 1);
}
-static inline void target_to_host_timeval(struct timeval *tv,
+static inline long target_to_host_timeval(struct timeval *tv,
target_ulong target_addr)
{
+ long ret = 0;
struct target_timeval *target_tv;
- lock_user_struct(target_tv, target_addr, 1);
+ if( (ret=lock_and_check_user_struct(&target_tv,target_addr,sizeof(*target_tv),1,PAGE_READ)) != 0 ) return -ret;
tv->tv_sec = tswapl(target_tv->tv_sec);
tv->tv_usec = tswapl(target_tv->tv_usec);
unlock_user_struct(target_tv, target_addr, 0);
}
-static inline void host_to_target_timeval(target_ulong target_addr,
+static inline long host_to_target_timeval(target_ulong target_addr,
const struct timeval *tv)
{
+ long ret = 0;
struct target_timeval *target_tv;
- lock_user_struct(target_tv, target_addr, 0);
+ if( (ret=lock_and_check_user_struct(&target_tv,target_addr,sizeof(*target_tv),0,PAGE_WRITE)) != 0 ) return -ret;
target_tv->tv_sec = tswapl(tv->tv_sec);
target_tv->tv_usec = tswapl(tv->tv_usec);
unlock_user_struct(target_tv, target_addr, 1);
@@ -464,21 +467,21 @@
int ok;
if (rfd_p) {
- target_rfds = lock_user(rfd_p, sizeof(target_long) * n, 1);
+ if( (ret=lock_and_check_user_struct(&target_rfds,rfd_p,sizeof(target_long)*n,1,PAGE_READ)) != 0 ) return -ret;
rfds_ptr = target_to_host_fds(&rfds, target_rfds, n);
} else {
target_rfds = NULL;
rfds_ptr = NULL;
}
if (wfd_p) {
- target_wfds = lock_user(wfd_p, sizeof(target_long) * n, 1);
+ if( (ret=lock_and_check_user_struct(&target_wfds,wfd_p,sizeof(target_long)*n,1,PAGE_READ)) != 0 ) return -ret;
wfds_ptr = target_to_host_fds(&wfds, target_wfds, n);
} else {
target_wfds = NULL;
wfds_ptr = NULL;
}
if (efd_p) {
- target_efds = lock_user(efd_p, sizeof(target_long) * n, 1);
+ if( (ret=lock_and_check_user_struct(&target_efds,efd_p,sizeof(target_long)*n,1,PAGE_READ)) != 0 ) return -ret;
efds_ptr = target_to_host_fds(&efds, target_efds, n);
} else {
target_efds = NULL;
@@ -486,7 +489,7 @@
}
if (target_tv) {
- target_to_host_timeval(&tv, target_tv);
+ if( (ret=target_to_host_timeval(&tv, target_tv)) != 0 ) return ret;
tv_ptr = &tv;
} else {
tv_ptr = NULL;
@@ -500,7 +503,7 @@
host_to_target_fds(target_efds, efds_ptr, n);
if (target_tv) {
- host_to_target_timeval(target_tv, &tv);
+ if( (ret=host_to_target_timeval(target_tv, &tv)) != 0 ) return ret;
}
}
if (target_rfds)
@@ -513,28 +516,34 @@
return ret;
}
-static inline void target_to_host_sockaddr(struct sockaddr *addr,
+static inline long target_to_host_sockaddr(struct sockaddr *addr,
target_ulong target_addr,
- socklen_t len)
+ socklen_t len,
+ int pg_access)
{
+ long ret = 0;
struct target_sockaddr *target_saddr;
- target_saddr = lock_user(target_addr, len, 1);
+ if( (ret=lock_and_check_user_struct(&target_saddr,target_addr,len,1,pg_access)) != 0 ) return -ret;
memcpy(addr, target_saddr, len);
addr->sa_family = tswap16(target_saddr->sa_family);
unlock_user(target_saddr, target_addr, 0);
+ return ret;
}
-static inline void host_to_target_sockaddr(target_ulong target_addr,
+static inline long host_to_target_sockaddr(target_ulong target_addr,
struct sockaddr *addr,
- socklen_t len)
+ socklen_t len,
+ int pg_access)
{
+ long ret = 0;
struct target_sockaddr *target_saddr;
- target_saddr = lock_user(target_addr, len, 0);
+ if( (ret=lock_and_check_user_struct(&target_saddr,target_addr,len,1,pg_access)) != 0 ) return -ret;
memcpy(target_saddr, addr, len);
target_saddr->sa_family = tswap16(addr->sa_family);
unlock_user(target_saddr, target_addr, len);
+ return ret;
}
/* ??? Should this also swap msgh->name? */
@@ -895,18 +904,20 @@
static long do_bind(int sockfd, target_ulong target_addr,
socklen_t addrlen)
{
+ long ret = 0;
void *addr = alloca(addrlen);
- target_to_host_sockaddr(addr, target_addr, addrlen);
+ if( (ret=target_to_host_sockaddr(addr, target_addr, addrlen,PAGE_READ)) != 0 ) return -ret;
return get_errno(bind(sockfd, addr, addrlen));
}
static long do_connect(int sockfd, target_ulong target_addr,
socklen_t addrlen)
{
+ long ret = 0;
void *addr = alloca(addrlen);
- target_to_host_sockaddr(addr, target_addr, addrlen);
+ if( (ret=target_to_host_sockaddr(addr, target_addr, addrlen,PAGE_READ)) != 0 ) return -ret;
return get_errno(connect(sockfd, addr, addrlen));
}
@@ -920,12 +931,23 @@
struct iovec *vec;
target_ulong target_vec;
- lock_user_struct(msgp, target_msg, 1);
+ if( send ) {
+ if( (ret=lock_and_check_user_struct(&msgp,target_msg,sizeof(*msgp),1,
+ PAGE_READ)) != 0 ) return -ret;
+ } else {
+ if( (ret=lock_and_check_user_struct(&msgp,target_msg,sizeof(*msgp),1,
+ PAGE_WRITE)) != 0 ) return -ret;
+ }
if (msgp->msg_name) {
msg.msg_namelen = tswap32(msgp->msg_namelen);
msg.msg_name = alloca(msg.msg_namelen);
- target_to_host_sockaddr(msg.msg_name, tswapl(msgp->msg_name),
- msg.msg_namelen);
+ if( send ) {
+ if( (ret=target_to_host_sockaddr(msg.msg_name, tswapl(msgp->msg_name),
+ msg.msg_namelen,PAGE_READ)) != 0 ) return -ret;
+ } else {
+ if( (ret=target_to_host_sockaddr(msg.msg_name, tswapl(msgp->msg_name),
+ msg.msg_namelen,PAGE_WRITE)) != 0 ) return -ret;
+ }
} else {
msg.msg_name = NULL;
msg.msg_namelen = 0;
@@ -958,11 +980,12 @@
{
socklen_t addrlen = tget32(target_addrlen);
void *addr = alloca(addrlen);
- long ret;
+ long ret,ret2;
ret = get_errno(accept(fd, addr, &addrlen));
if (!is_error(ret)) {
- host_to_target_sockaddr(target_addr, addr, addrlen);
+ if( (ret2=host_to_target_sockaddr(target_addr, addr, addrlen, PAGE_WRITE)) != 0 ) return -ret2;
+ if( (ret2=page_check_range(target_addrlen,sizeof(socklen_t),PAGE_WRITE)) != 0 ) return -ret2;
tput32(target_addrlen, addrlen);
}
return ret;
@@ -971,13 +994,18 @@
static long do_getpeername(int fd, target_ulong target_addr,
target_ulong target_addrlen)
{
- socklen_t addrlen = tget32(target_addrlen);
- void *addr = alloca(addrlen);
- long ret;
+ socklen_t addrlen;
+ void *addr;
+ long ret,ret2;
+
+ if( (ret=page_check_range(target_addrlen,sizeof(socklen_t),PAGE_READ)) != 0 ) return -ret;
+ addrlen = tget32(target_addrlen);
+ addr = alloca(addrlen);
ret = get_errno(getpeername(fd, addr, &addrlen));
if (!is_error(ret)) {
- host_to_target_sockaddr(target_addr, addr, addrlen);
+ if( (ret2=host_to_target_sockaddr(target_addr, addr, addrlen, PAGE_WRITE)) != 0 ) return -ret2;
+ if( (ret2=page_check_range(target_addrlen,sizeof(socklen_t),PAGE_WRITE)) != 0 ) return -ret2;
tput32(target_addrlen, addrlen);
}
return ret;
@@ -986,13 +1014,17 @@
static long do_getsockname(int fd, target_ulong target_addr,
target_ulong target_addrlen)
{
- socklen_t addrlen = tget32(target_addrlen);
- void *addr = alloca(addrlen);
- long ret;
+ socklen_t addrlen;
+ void *addr;
+ long ret,ret2;
+
+ if( (ret=page_check_range(target_addrlen,sizeof(socklen_t),PAGE_WRITE)) != 0 ) return -ret;
+ addrlen = tget32(target_addrlen);
+ addr = alloca(addrlen);
ret = get_errno(getsockname(fd, addr, &addrlen));
if (!is_error(ret)) {
- host_to_target_sockaddr(target_addr, addr, addrlen);
+ if( (ret2=host_to_target_sockaddr(target_addr, addr, addrlen, PAGE_WRITE)) ) return -ret2;
tput32(target_addrlen, addrlen);
}
return ret;
@@ -1019,10 +1051,10 @@
void *host_msg;
long ret;
- host_msg = lock_user(msg, len, 1);
+ if( (ret=lock_and_check_user_struct(&host_msg,msg,len,1,PAGE_READ)) != 0 ) return -ret;
if (target_addr) {
addr = alloca(addrlen);
- target_to_host_sockaddr(addr, target_addr, addrlen);
+ if( (ret=target_to_host_sockaddr(addr, target_addr, addrlen, PAGE_READ)) != 0 ) return -ret;
ret = get_errno(sendto(fd, host_msg, len, flags, addr, addrlen));
} else {
ret = get_errno(send(fd, host_msg, len, flags));
@@ -1037,9 +1069,9 @@
socklen_t addrlen;
void *addr;
void *host_msg;
- long ret;
+ long ret,ret2;
- host_msg = lock_user(msg, len, 0);
+ if( (ret2=lock_and_check_user_struct(&host_msg,msg,len,0,PAGE_WRITE)) != 0 ) return -ret2;
if (target_addr) {
addrlen = tget32(target_addrlen);
addr = alloca(addrlen);
@@ -1050,7 +1082,7 @@
}
if (!is_error(ret)) {
if (target_addr) {
- host_to_target_sockaddr(target_addr, addr, addrlen);
+ if( (ret2=host_to_target_sockaddr(target_addr, addr, addrlen, PAGE_WRITE)) != 0 ) return -ret2;
tput32(target_addrlen, addrlen);
}
unlock_user(host_msg, msg, len);
@@ -1257,13 +1289,15 @@
target_ulong __unused4;
};
-static inline void target_to_host_ipc_perm(struct ipc_perm *host_ip,
- target_ulong target_addr)
+static inline long target_to_host_ipc_perm(struct ipc_perm *host_ip,
+ target_ulong target_addr,
+ int pg_access)
{
+ long ret = 0;
struct target_ipc_perm *target_ip;
struct target_semid_ds *target_sd;
- lock_user_struct(target_sd, target_addr, 1);
+ if( (ret=lock_and_check_user_struct(&target_sd,target_addr,sizeof(*target_sd),1,pg_access)) ) return -ret;
target_ip=&(target_sd->sem_perm);
host_ip->__key = tswapl(target_ip->__key);
host_ip->uid = tswapl(target_ip->uid);
@@ -1272,15 +1306,19 @@
host_ip->cgid = tswapl(target_ip->cgid);
host_ip->mode = tswapl(target_ip->mode);
unlock_user_struct(target_sd, target_addr, 0);
+
+ return ret;
}
-static inline void host_to_target_ipc_perm(target_ulong target_addr,
- struct ipc_perm *host_ip)
+static inline long host_to_target_ipc_perm(target_ulong target_addr,
+ struct ipc_perm *host_ip,
+ int pg_access)
{
+ long ret = 0;
struct target_ipc_perm *target_ip;
struct target_semid_ds *target_sd;
- lock_user_struct(target_sd, target_addr, 0);
+ if( (ret=lock_and_check_user_struct(&target_sd,target_addr,sizeof(*target_sd),0,pg_access)) ) return -ret;
target_ip = &(target_sd->sem_perm);
target_ip->__key = tswapl(host_ip->__key);
target_ip->uid = tswapl(host_ip->uid);
@@ -1289,32 +1327,42 @@
target_ip->cgid = tswapl(host_ip->cgid);
target_ip->mode = tswapl(host_ip->mode);
unlock_user_struct(target_sd, target_addr, 1);
+
+ return ret;
}
-static inline void target_to_host_semid_ds(struct semid_ds *host_sd,
- target_ulong target_addr)
+static inline long target_to_host_semid_ds(struct semid_ds *host_sd,
+ target_ulong target_addr,
+ int pg_access)
{
+ long ret = 0;
struct target_semid_ds *target_sd;
- lock_user_struct(target_sd, target_addr, 1);
- target_to_host_ipc_perm(&(host_sd->sem_perm),target_addr);
+ if( (ret=lock_and_check_user_struct(&target_sd,target_addr,sizeof(*target_sd),1,pg_access)) != 0 ) return -ret;
+ if( (ret=target_to_host_ipc_perm(&(host_sd->sem_perm),target_addr,pg_access)) != 0 ) return ret;
host_sd->sem_nsems = tswapl(target_sd->sem_nsems);
host_sd->sem_otime = tswapl(target_sd->sem_otime);
host_sd->sem_ctime = tswapl(target_sd->sem_ctime);
unlock_user_struct(target_sd, target_addr, 0);
+
+ return ret;
}
-static inline void host_to_target_semid_ds(target_ulong target_addr,
- struct semid_ds *host_sd)
+static inline long host_to_target_semid_ds(target_ulong target_addr,
+ struct semid_ds *host_sd,
+ int pg_access)
{
+ long ret = 0;
struct target_semid_ds *target_sd;
- lock_user_struct(target_sd, target_addr, 0);
- host_to_target_ipc_perm(target_addr,&(host_sd->sem_perm));
+ if( (ret=lock_and_check_user_struct(&target_sd,target_addr,sizeof(*target_sd),0,pg_access)) != 0 ) return -ret;
+ if( (ret=host_to_target_ipc_perm(target_addr,&(host_sd->sem_perm),pg_access)) != 0 ) return ret;
target_sd->sem_nsems = tswapl(host_sd->sem_nsems);
target_sd->sem_otime = tswapl(host_sd->sem_otime);
target_sd->sem_ctime = tswapl(host_sd->sem_ctime);
unlock_user_struct(target_sd, target_addr, 1);
+
+ return ret;
}
union semun {
@@ -1329,67 +1377,75 @@
unsigned short int *array;
};
-static inline void target_to_host_semun(unsigned long cmd,
+static inline long target_to_host_semun(unsigned long cmd,
union semun *host_su,
target_ulong target_addr,
- struct semid_ds *ds)
+ struct semid_ds *ds,
+ int pg_access)
{
+ long ret = 0;
union target_semun *target_su;
switch( cmd ) {
case IPC_STAT:
case IPC_SET:
- lock_user_struct(target_su, target_addr, 1);
- target_to_host_semid_ds(ds,target_su->buf);
+ if( (ret=lock_and_check_user_struct(&target_su,target_addr,sizeof(*target_su),1,pg_access)) != 0 ) return -ret;
+ if( (ret=target_to_host_semid_ds(ds,target_su->buf, pg_access)) != 0 ) return -ret;
host_su->buf = ds;
unlock_user_struct(target_su, target_addr, 0);
break;
case GETVAL:
case SETVAL:
- lock_user_struct(target_su, target_addr, 1);
+ if( (ret=lock_and_check_user_struct(&target_su,target_addr,sizeof(*target_su),1,pg_access)) != 0 ) return -ret;
host_su->val = tswapl(target_su->val);
unlock_user_struct(target_su, target_addr, 0);
break;
case GETALL:
case SETALL:
- lock_user_struct(target_su, target_addr, 1);
+ if( (ret=lock_and_check_user_struct(&target_su,target_addr,sizeof(*target_su),1,pg_access)) != 0 ) return -ret;
*host_su->array = tswap16(*target_su->array);
unlock_user_struct(target_su, target_addr, 0);
break;
default:
gemu_log("semun operation not fully supported: %d\n", (int)cmd);
}
+
+ return ret;
}
-static inline void host_to_target_semun(unsigned long cmd,
+static inline long host_to_target_semun(unsigned long cmd,
target_ulong target_addr,
union semun *host_su,
- struct semid_ds *ds)
+ struct semid_ds *ds,
+ int pg_access)
{
+ long ret = 0;
union target_semun *target_su;
switch( cmd ) {
case IPC_STAT:
case IPC_SET:
- lock_user_struct(target_su, target_addr, 0);
- host_to_target_semid_ds(target_su->buf,ds);
+ if( (ret=lock_and_check_user_struct(&target_su,target_addr,sizeof(*target_su),0,pg_access)) != 0 ) return -ret;
+ if( (ret=host_to_target_semid_ds(target_su->buf,ds, pg_access)) != 0 ) return -ret;
unlock_user_struct(target_su, target_addr, 1);
break;
case GETVAL:
case SETVAL:
- lock_user_struct(target_su, target_addr, 0);
+ if( (ret=lock_and_check_user_struct(&target_su,target_addr,sizeof(*target_su),0,pg_access)) != 0 ) return -ret;
target_su->val = tswapl(host_su->val);
unlock_user_struct(target_su, target_addr, 1);
break;
case GETALL:
case SETALL:
- lock_user_struct(target_su, target_addr, 0);
+ if( (ret=lock_and_check_user_struct(&target_su,target_addr,sizeof(*target_su),0,pg_access)) != 0 ) return -ret;
*target_su->array = tswap16(*host_su->array);
unlock_user_struct(target_su, target_addr, 1);
break;
default:
gemu_log("semun operation not fully supported: %d\n", (int)cmd);
}
+
+ return ret;
}
static inline long do_semctl(long first, long second, long third, long ptr)
@@ -1401,34 +1457,34 @@
switch( cmd ) {
case GETVAL:
- target_to_host_semun(cmd,&arg,ptr,&dsarg);
+ if( (ret=target_to_host_semun(cmd,&arg,ptr,&dsarg,PAGE_WRITE)) != 0 ) return -ret;
ret = get_errno(semctl(first, second, cmd, arg));
- host_to_target_semun(cmd,ptr,&arg,&dsarg);
+ host_to_target_semun(cmd,ptr,&arg,&dsarg,PAGE_WRITE);
break;
case SETVAL:
- target_to_host_semun(cmd,&arg,ptr,&dsarg);
+ if( (ret=target_to_host_semun(cmd,&arg,ptr,&dsarg,PAGE_READ)) != 0 ) return -ret;
ret = get_errno(semctl(first, second, cmd, arg));
- host_to_target_semun(cmd,ptr,&arg,&dsarg);
+ host_to_target_semun(cmd,ptr,&arg,&dsarg,PAGE_READ);
break;
case GETALL:
- target_to_host_semun(cmd,&arg,ptr,&dsarg);
+ if( (ret=target_to_host_semun(cmd,&arg,ptr,&dsarg,PAGE_WRITE)) != 0 ) return -ret;
ret = get_errno(semctl(first, second, cmd, arg));
- host_to_target_semun(cmd,ptr,&arg,&dsarg);
+ host_to_target_semun(cmd,ptr,&arg,&dsarg,PAGE_WRITE);
break;
case SETALL:
- target_to_host_semun(cmd,&arg,ptr,&dsarg);
+ if( (ret=target_to_host_semun(cmd,&arg,ptr,&dsarg,PAGE_READ)) != 0 ) return -ret;
ret = get_errno(semctl(first, second, cmd, arg));
- host_to_target_semun(cmd,ptr,&arg,&dsarg);
+ host_to_target_semun(cmd,ptr,&arg,&dsarg,PAGE_READ);
break;
case IPC_STAT:
- target_to_host_semun(cmd,&arg,ptr,&dsarg);
+ if( (ret=target_to_host_semun(cmd,&arg,ptr,&dsarg,PAGE_WRITE)) != 0 ) return -ret;
ret = get_errno(semctl(first, second, cmd, arg));
- host_to_target_semun(cmd,ptr,&arg,&dsarg);
+ host_to_target_semun(cmd,ptr,&arg,&dsarg,PAGE_READ);
break;
case IPC_SET:
- target_to_host_semun(cmd,&arg,ptr,&dsarg);
+ if( (ret=target_to_host_semun(cmd,&arg,ptr,&dsarg,PAGE_READ)) != 0 ) return -ret;
ret = get_errno(semctl(first, second, cmd, arg));
- host_to_target_semun(cmd,ptr,&arg,&dsarg);
+ host_to_target_semun(cmd,ptr,&arg,&dsarg,PAGE_READ);
break;
default:
ret = get_errno(semctl(first, second, cmd, arg));
@@ -1455,13 +1511,15 @@
target_ulong __unused5;
};
-static inline void target_to_host_msqid_ds(struct msqid_ds *host_md,
- target_ulong target_addr)
+static inline long target_to_host_msqid_ds(struct msqid_ds *host_md,
+ target_ulong target_addr,
+ int pg_access)
{
+ long ret = 0;
struct target_msqid_ds *target_md;
- lock_user_struct(target_md, target_addr, 1);
- target_to_host_ipc_perm(&(host_md->msg_perm),target_addr);
+ if( (ret=lock_and_check_user_struct(&target_md,target_addr,sizeof(*target_md),1,pg_access)) != 0 ) return -ret;
+ if( (ret=target_to_host_ipc_perm(&(host_md->msg_perm),target_addr,pg_access)) != 0 ) return ret;
host_md->msg_stime = tswapl(target_md->msg_stime);
host_md->msg_rtime = tswapl(target_md->msg_rtime);
host_md->msg_ctime = tswapl(target_md->msg_ctime);
@@ -1471,15 +1529,18 @@
host_md->msg_lspid = tswapl(target_md->msg_lspid);
host_md->msg_lrpid = tswapl(target_md->msg_lrpid);
unlock_user_struct(target_md, target_addr, 0);
+ return ret;
}
-static inline void host_to_target_msqid_ds(target_ulong target_addr,
- struct msqid_ds *host_md)
+static inline long host_to_target_msqid_ds(target_ulong target_addr,
+ struct msqid_ds *host_md,
+ int pg_access)
{
+ long ret = 0;
struct target_msqid_ds *target_md;
- lock_user_struct(target_md, target_addr, 0);
- host_to_target_ipc_perm(target_addr,&(host_md->msg_perm));
+ if( (ret=lock_and_check_user_struct(&target_md,target_addr,sizeof(*target_md),0,pg_access)) != 0 ) return -ret;
+ if( (ret=host_to_target_ipc_perm(target_addr,&(host_md->msg_perm),pg_access)) != 0 ) return ret;
target_md->msg_stime = tswapl(host_md->msg_stime);
target_md->msg_rtime = tswapl(host_md->msg_rtime);
target_md->msg_ctime = tswapl(host_md->msg_ctime);
@@ -1489,6 +1550,8 @@
target_md->msg_lspid = tswapl(host_md->msg_lspid);
target_md->msg_lrpid = tswapl(host_md->msg_lrpid);
unlock_user_struct(target_md, target_addr, 1);
+
+ return ret;
}
static inline long do_msgctl(long first, long second, long ptr)
@@ -1498,10 +1561,15 @@
long ret = 0;
switch( cmd ) {
case IPC_STAT:
+ if( (ret=target_to_host_msqid_ds(&dsarg,ptr,PAGE_WRITE)) != 0 ) return -ret;
+ ret = get_errno(msgctl(first, cmd, &dsarg));
+ host_to_target_msqid_ds(ptr,&dsarg,PAGE_WRITE);
+ break;
case IPC_SET:
- target_to_host_msqid_ds(&dsarg,ptr);
+ if( (ret=target_to_host_msqid_ds(&dsarg,ptr,PAGE_READ)) != 0 ) return -ret;
ret = get_errno(msgctl(first, cmd, &dsarg));
- host_to_target_msqid_ds(ptr,&dsarg);
+ host_to_target_msqid_ds(ptr,&dsarg,PAGE_WRITE);
+ break;
default:
ret = get_errno(msgctl(first, cmd, &dsarg));
}
@@ -1519,7 +1587,7 @@
struct msgbuf *host_mb;
long ret = 0;
- lock_user_struct(target_mb,msgp,0);
+ if( (ret=lock_and_check_user_struct(&target_mb,msgp,sizeof(long)+msgsz,1,PAGE_READ)) != 0 ) return -ret;
host_mb = malloc(msgsz+sizeof(long));
host_mb->mtype = tswapl(target_mb->mtype);
memcpy(host_mb->mtext,target_mb->mtext,msgsz);
@@ -1536,7 +1604,7 @@
struct msgbuf *host_mb;
long ret = 0;
- lock_user_struct(target_mb, msgp, 0);
+ if( (ret=lock_and_check_user_struct(&target_mb,msgp,sizeof(long)+msgsz,0,PAGE_WRITE)) != 0 ) return -ret;
host_mb = malloc(msgsz+sizeof(long));
ret = get_errno(msgrcv(msqid, host_mb, msgsz, 1, msgflg));
if (ret > 0)
@@ -2016,6 +2084,7 @@
static int write_ldt(CPUX86State *env,
target_ulong ptr, unsigned long bytecount, int oldmode)
{
+ long ret = 0;
struct target_modify_ldt_ldt_s ldt_info;
struct target_modify_ldt_ldt_s *target_ldt_info;
int seg_32bit, contents, read_exec_only, limit_in_pages;
@@ -2024,7 +2093,7 @@
if (bytecount != sizeof(ldt_info))
return -EINVAL;
- lock_user_struct(target_ldt_info, ptr, 1);
+ if( (ret=lock_and_check_user_struct(&target_ldt_info,ptr,sizeof(struct target_modify_ldt_ldt_s),1,PAGE_READ)) != 0 ) return -ret;
ldt_info.entry_number = tswap32(target_ldt_info->entry_number);
ldt_info.base_addr = tswapl(target_ldt_info->base_addr);
ldt_info.limit = tswap32(target_ldt_info->limit);
@@ -2223,7 +2292,7 @@
switch(cmd) {
case TARGET_F_GETLK:
- lock_user_struct(target_fl, arg, 1);
+ if( (ret=lock_and_check_user_struct(&target_fl,arg,sizeof(struct target_flock),1,PAGE_READ)) != 0 ) return -ret;
fl.l_type = tswap16(target_fl->l_type);
fl.l_whence = tswap16(target_fl->l_whence);
fl.l_start = tswapl(target_fl->l_start);
@@ -2232,6 +2301,7 @@
unlock_user_struct(target_fl, arg, 0);
ret = fcntl(fd, cmd, &fl);
if (ret == 0) {
+ if( (ret=lock_and_check_user_struct(&target_fl,arg,sizeof(struct target_flock),0,PAGE_WRITE)) != 0 ) return -ret;
lock_user_struct(target_fl, arg, 0);
target_fl->l_type = tswap16(fl.l_type);
target_fl->l_whence = tswap16(fl.l_whence);
@@ -2244,7 +2314,7 @@
case TARGET_F_SETLK:
case TARGET_F_SETLKW:
- lock_user_struct(target_fl, arg, 1);
+ if( (ret=lock_and_check_user_struct(&target_fl,arg,sizeof(struct target_flock),1,PAGE_READ)) != 0 ) return -ret;
fl.l_type = tswap16(target_fl->l_type);
fl.l_whence = tswap16(target_fl->l_whence);
fl.l_start = tswapl(target_fl->l_start);
@@ -2255,7 +2325,7 @@
break;
case TARGET_F_GETLK64:
- lock_user_struct(target_fl64, arg, 1);
+ if( (ret=lock_and_check_user_struct(&target_fl64,arg,sizeof(struct target_flock64),1,PAGE_READ)) != 0 ) return -ret;
fl64.l_type = tswap16(target_fl64->l_type) >> 1;
fl64.l_whence = tswap16(target_fl64->l_whence);
fl64.l_start = tswapl(target_fl64->l_start);
@@ -2264,7 +2334,7 @@
unlock_user_struct(target_fl64, arg, 0);
ret = fcntl(fd, cmd >> 1, &fl64);
if (ret == 0) {
- lock_user_struct(target_fl64, arg, 0);
+ if( (ret=lock_and_check_user_struct(&target_fl64,arg,sizeof(struct target_flock64),0,PAGE_WRITE)) != 0 ) return -ret;
target_fl64->l_type = tswap16(fl64.l_type) >> 1;
target_fl64->l_whence = tswap16(fl64.l_whence);
target_fl64->l_start = tswapl(fl64.l_start);
@@ -2275,7 +2345,7 @@
break;
case TARGET_F_SETLK64:
case TARGET_F_SETLKW64:
- lock_user_struct(target_fl64, arg, 1);
+ if( (ret=lock_and_check_user_struct(&target_fl64,arg,sizeof(struct target_flock64),1,PAGE_READ)) != 0 ) return -ret;
fl64.l_type = tswap16(target_fl64->l_type) >> 1;
fl64.l_whence = tswap16(target_fl64->l_whence);
fl64.l_start = tswapl(target_fl64->l_start);
@@ -2417,23 +2487,26 @@
}
#endif
-static inline void target_to_host_timespec(struct timespec *host_ts,
+static inline long target_to_host_timespec(struct timespec *host_ts,
target_ulong target_addr)
{
+ long ret = 0;
struct target_timespec *target_ts;
- lock_user_struct(target_ts, target_addr, 1);
+ if( (ret=lock_and_check_user_struct(&target_ts,target_addr,sizeof(struct target_timespec),1,PAGE_READ)) != 0 ) return -ret;
host_ts->tv_sec = tswapl(target_ts->tv_sec);
host_ts->tv_nsec = tswapl(target_ts->tv_nsec);
unlock_user_struct(target_ts, target_addr, 0);
}
-static inline void host_to_target_timespec(target_ulong target_addr,
+static inline long host_to_target_timespec(target_ulong target_addr,
struct timespec *host_ts)
{
+ long ret = 0;
struct target_timespec *target_ts;
lock_user_struct(target_ts, target_addr, 0);
+ if( (ret=lock_and_check_user_struct(&target_ts,target_addr,sizeof(struct target_timespec),0,PAGE_WRITE)) != 0 ) return -ret;
target_ts->tv_sec = tswapl(host_ts->tv_sec);
target_ts->tv_nsec = tswapl(host_ts->tv_nsec);
unlock_user_struct(target_ts, target_addr, 1);
@@ -2442,7 +2515,7 @@
long do_syscall(void *cpu_env, int num, long arg1, long arg2, long arg3,
long arg4, long arg5, long arg6)
{
- long ret;
+ long ret = 0;
struct stat st;
struct statfs stfs;
void *p;
@@ -2669,7 +2742,7 @@
struct utimbuf tbuf, *host_tbuf;
struct target_utimbuf *target_tbuf;
if (arg2) {
- lock_user_struct(target_tbuf, arg2, 1);
+ if( (ret=lock_and_check_user_struct(&target_tbuf,arg2,sizeof(struct target_utimbuf),1,PAGE_READ)) != 0 ) return -ret;
tbuf.actime = tswapl(target_tbuf->actime);
tbuf.modtime = tswapl(target_tbuf->modtime);
unlock_user_struct(target_tbuf, arg2, 0);
@@ -2687,9 +2760,9 @@
{
struct timeval *tvp, tv[2];
if (arg2) {
- target_to_host_timeval(&tv[0], arg2);
- target_to_host_timeval(&tv[1],
- arg2 + sizeof (struct target_timeval));
+ if( (ret=target_to_host_timeval(&tv[0], arg2)) != 0 ) return ret;
+ if( (ret=target_to_host_timeval(&tv[1],
+ arg2 + sizeof (struct target_timeval))) != 0 ) return ret;
tvp = tv;
} else {
tvp = NULL;
@@ -2858,7 +2931,7 @@
struct target_old_sigaction *old_act;
struct target_sigaction act, oact, *pact;
if (arg2) {
- lock_user_struct(old_act, arg2, 1);
+ if( (ret=lock_and_check_user_struct(&old_act,arg2,sizeof(*old_act),1,PAGE_READ)) != 0 ) return -ret;
act._sa_handler = old_act->_sa_handler;
target_siginitset(&act.sa_mask, old_act->sa_mask);
act.sa_flags = old_act->sa_flags;
@@ -2870,7 +2943,7 @@
}
ret = get_errno(do_sigaction(arg1, pact, &oact));
if (!is_error(ret) && arg3) {
- lock_user_struct(old_act, arg3, 0);
+ if( (ret=lock_and_check_user_struct(&old_act,arg3,sizeof(*old_act),0,PAGE_WRITE)) != 0 ) return -ret;
old_act->_sa_handler = oact._sa_handler;
old_act->sa_mask = oact.sa_mask.sig[0];
old_act->sa_flags = oact.sa_flags;
@@ -2881,7 +2954,7 @@
struct target_sigaction act, oact, *pact, *old_act;
if (arg2) {
- lock_user_struct(old_act, arg2, 1);
+ if( (ret=lock_and_check_user_struct(&old_act,arg2,sizeof(*old_act),1,PAGE_READ)) != 0 ) return -ret;
act._sa_handler = old_act->_sa_handler;
target_siginitset(&act.sa_mask, old_act->sa_mask.sig[0]);
act.sa_flags = old_act->sa_flags;
@@ -2894,7 +2967,7 @@
ret = get_errno(do_sigaction(arg1, pact, &oact));
if (!is_error(ret) && arg3) {
- lock_user_struct(old_act, arg3, 0);
+ if( (ret=lock_and_check_user_struct(&old_act,arg3,sizeof(*old_act),0,PAGE_WRITE)) != 0 ) return -ret;
old_act->_sa_handler = oact._sa_handler;
old_act->sa_flags = oact.sa_flags;
old_act->sa_mask.sig[0] = oact.sa_mask.sig[0];
@@ -2912,12 +2985,14 @@
struct target_sigaction *act;
struct target_sigaction *oact;
- if (arg2)
- lock_user_struct(act, arg2, 1);
+ if (arg2) {
+ if( (ret=lock_and_check_user_struct(&act,arg2,sizeof(*act),1,PAGE_READ)) != 0 ) return -ret;
+ }
else
act = NULL;
- if (arg3)
- lock_user_struct(oact, arg3, 0);
+ if (arg3) {
+ if( (ret=lock_and_check_user_struct(&oact,arg2,sizeof(*oact),0,PAGE_WRITE)) != 0 ) return -ret;
+ }
else
oact = NULL;
ret = get_errno(do_sigaction(arg1, act, oact));
@@ -3044,7 +3119,7 @@
sigset_t set;
ret = get_errno(sigpending(&set));
if (!is_error(ret)) {
- p = lock_user(arg1, sizeof(target_sigset_t), 0);
+ if( (ret=lock_and_check_user_struct(&p,arg1,sizeof(target_sigset_t),0,PAGE_WRITE)) != 0 ) return -ret;
host_to_target_sigset(p, &set);
unlock_user(p, arg1, sizeof(target_sigset_t));
}
@@ -3054,7 +3129,7 @@
case TARGET_NR_sigsuspend:
{
sigset_t set;
- p = lock_user(arg1, sizeof(target_sigset_t), 1);
+ if( (ret=lock_and_check_user_struct(&p,arg1,sizeof(target_sigset_t),1,PAGE_READ)) != 0 ) return -ret;
target_to_host_old_sigset(&set, p);
unlock_user(p, arg1, 0);
ret = get_errno(sigsuspend(&set));
@@ -3064,7 +3139,7 @@
case TARGET_NR_rt_sigsuspend:
{
sigset_t set;
- p = lock_user(arg1, sizeof(target_sigset_t), 1);
+ if( (ret=lock_and_check_user_struct(&p,arg1,sizeof(target_sigset_t),1,PAGE_READ)) != 0 ) return -ret;
target_to_host_sigset(&set, p);
unlock_user(p, arg1, 0);
ret = get_errno(sigsuspend(&set));
@@ -3076,18 +3151,18 @@
struct timespec uts, *puts;
siginfo_t uinfo;
- p = lock_user(arg1, sizeof(target_sigset_t), 1);
+ if( (ret=lock_and_check_user_struct(&p,arg1,sizeof(target_sigset_t),1,PAGE_READ)) != 0 ) return -ret;
target_to_host_sigset(&set, p);
unlock_user(p, arg1, 0);
if (arg3) {
puts = &uts;
- target_to_host_timespec(puts, arg3);
+ if( (ret=target_to_host_timespec(puts, arg3)) != 0 ) return ret;
} else {
puts = NULL;
}
ret = get_errno(sigtimedwait(&set, &uinfo, puts));
if (!is_error(ret) && arg2) {
- p = lock_user(arg2, sizeof(target_sigset_t), 0);
+ if( (ret=lock_and_check_user_struct(&p,arg2,sizeof(target_sigset_t),0,PAGE_WRITE)) != 0 ) return -ret;
host_to_target_siginfo(p, &uinfo);
unlock_user(p, arg2, sizeof(target_sigset_t));
}
@@ -3096,7 +3171,7 @@
case TARGET_NR_rt_sigqueueinfo:
{
siginfo_t uinfo;
- p = lock_user(arg3, sizeof(target_sigset_t), 1);
+ if( (ret=lock_and_check_user_struct(&p,arg3,sizeof(target_sigset_t),1,PAGE_READ)) != 0 ) return -ret;
target_to_host_siginfo(&uinfo, p);
unlock_user(p, arg1, 0);
ret = get_errno(sys_rt_sigqueueinfo(arg1, arg2, &uinfo));
@@ -3151,7 +3226,7 @@
struct rusage rusage;
ret = get_errno(getrusage(arg1, &rusage));
if (!is_error(ret)) {
- host_to_target_rusage(arg2, &rusage);
+ if( (ret=host_to_target_rusage(arg2, &rusage)) != 0 ) return ret;
}
}
break;
@@ -3160,14 +3235,14 @@
struct timeval tv;
ret = get_errno(gettimeofday(&tv, NULL));
if (!is_error(ret)) {
- host_to_target_timeval(arg1, &tv);
+ if( (ret=host_to_target_timeval(arg1, &tv)) != 0 ) return ret;
}
}
break;
case TARGET_NR_settimeofday:
{
struct timeval tv;
- target_to_host_timeval(&tv, arg1);
+ if( (ret=target_to_host_timeval(&tv, arg1)) != 0 ) return ret;
ret = get_errno(settimeofday(&tv, NULL));
}
break;
@@ -3486,19 +3561,19 @@
if (arg2) {
pvalue = &value;
- target_to_host_timeval(&pvalue->it_interval,
- arg2);
- target_to_host_timeval(&pvalue->it_value,
- arg2 + sizeof(struct target_timeval));
+ if( (ret=target_to_host_timeval(&pvalue->it_interval,
+ arg2)) != 0 ) return ret;
+ if( (ret=target_to_host_timeval(&pvalue->it_value,
+ arg2 + sizeof(struct target_timeval))) != 0 ) return ret;
} else {
pvalue = NULL;
}
ret = get_errno(setitimer(arg1, pvalue, &ovalue));
if (!is_error(ret) && arg3) {
- host_to_target_timeval(arg3,
- &ovalue.it_interval);
- host_to_target_timeval(arg3 + sizeof(struct target_timeval),
- &ovalue.it_value);
+ if( (ret=host_to_target_timeval(arg3,
+ &ovalue.it_interval)) != 0 ) return ret;
+ if( (ret=host_to_target_timeval(arg3 + sizeof(struct target_timeval),
+ &ovalue.it_value)) != 0 ) return ret;
}
}
break;
@@ -3508,10 +3583,10 @@
ret = get_errno(getitimer(arg1, &value));
if (!is_error(ret) && arg2) {
- host_to_target_timeval(arg2,
- &value.it_interval);
- host_to_target_timeval(arg2 + sizeof(struct target_timeval),
- &value.it_value);
+ if( (ret=host_to_target_timeval(arg2,
+ &value.it_interval)) != 0 ) return ret;
+ if( (ret=host_to_target_timeval(arg2 + sizeof(struct target_timeval),
+ &value.it_value)) != 0 ) return ret;
}
}
break;
@@ -3532,7 +3607,7 @@
if (!is_error(ret)) {
struct target_stat *target_st;
- lock_user_struct(target_st, arg2, 0);
+ if( (ret=lock_and_check_user_struct(&target_st,arg2,sizeof(*target_st),9,PAGE_WRITE)) != 0 ) return -ret;
#if defined(TARGET_MIPS)
target_st->st_dev = tswap32(st.st_dev);
#else
@@ -3963,17 +4038,17 @@
struct timespec ts;
ret = get_errno(sched_rr_get_interval(arg1, &ts));
if (!is_error(ret)) {
- host_to_target_timespec(arg2, &ts);
+ if( (ret=host_to_target_timespec(arg2, &ts)) != 0 ) return ret;
}
}
break;
case TARGET_NR_nanosleep:
{
struct timespec req, rem;
- target_to_host_timespec(&req, arg1);
+ if( (ret=target_to_host_timespec(&req, arg1)) != 0 ) return ret;
ret = get_errno(nanosleep(&req, &rem));
if (is_error(ret) && arg2) {
- host_to_target_timespec(arg2, &rem);
+ if( (ret=host_to_target_timespec(arg2, &rem)) != 0 ) return ret;
}
}
break;
@@ -4070,6 +4145,7 @@
#ifdef TARGET_NR_stat64
case TARGET_NR_stat64:
p = lock_user_string(arg1);
+ if( ret=page_check_range(p,1,PAGE_READ) ) return -ret;
ret = get_errno(stat(path(p), &st));
unlock_user(p, arg1, 0);
goto do_stat64;
@@ -4077,6 +4153,7 @@
#ifdef TARGET_NR_lstat64
case TARGET_NR_lstat64:
p = lock_user_string(arg1);
+ if( ret=page_check_range(p,1,PAGE_READ) ) return -ret;
ret = get_errno(lstat(path(p), &st));
unlock_user(p, arg1, 0);
goto do_stat64;
@@ -4090,7 +4167,7 @@
#ifdef TARGET_ARM
if (((CPUARMState *)cpu_env)->eabi) {
struct target_eabi_stat64 *target_st;
- lock_user_struct(target_st, arg2, 1);
+ if( (ret=lock_and_check_user_struct(&target_st,arg2,sizeof(*target_st),1,PAGE_WRITE)) != 0 ) return -ret;
memset(target_st, 0, sizeof(struct target_eabi_stat64));
/* put_user is probably wrong. */
put_user(st.st_dev, &target_st->st_dev);
@@ -4115,7 +4192,7 @@
#endif
{
struct target_stat64 *target_st;
- lock_user_struct(target_st, arg2, 1);
+ if( (ret=lock_and_check_user_struct(&target_st,arg2,sizeof(*target_st),1,PAGE_WRITE)) != 0 ) return -ret;
memset(target_st, 0, sizeof(struct target_stat64));
/* ??? put_user is probably wrong. */
put_user(st.st_dev, &target_st->st_dev);
@@ -4581,7 +4658,7 @@
struct timespec ts;
ret = get_errno(clock_gettime(arg1, &ts));
if (!is_error(ret)) {
- host_to_target_timespec(arg2, &ts);
+ if( (ret=host_to_target_timespec(arg2, &ts)) != 0 ) return ret;
}
break;
}
@@ -4592,7 +4669,7 @@
struct timespec ts;
ret = get_errno(clock_getres(arg1, &ts));
if (!is_error(ret)) {
- host_to_target_timespec(arg2, &ts);
+ if( (ret=host_to_target_timespec(arg2, &ts)) != 0 ) return ret;
}
break;
}
Index: qemu/linux-user/qemu.h
===================================================================
--- qemu.orig/linux-user/qemu.h 2007-06-03 20:36:54.000000000 -0400
+++ qemu/linux-user/qemu.h 2007-06-03 20:37:10.000000000 -0400
@@ -295,6 +295,15 @@
#define unlock_user_struct(host_ptr, guest_addr, copy) \
unlock_user(host_ptr, guest_addr, (copy) ? sizeof(*host_ptr) : 0)
+static inline long lock_and_check_user_struct(void *host_addr, target_ulong guest_addr, long len, int copy, int pg_access)
+{
+ long *haddr, ret = 0;
+ haddr = (long *)host_addr;
+ if( (ret=page_check_range(guest_addr,len,pg_access)) != 0 ) return ret;
+ *haddr = (long)lock_user(guest_addr, len, copy);
+ return 0;
+}
+
#define tget8(addr) ldub(addr)
#define tput8(addr, val) stb(addr, val)
#define tget16(addr) lduw(addr)
reply other threads:[~2007-06-04 0:48 UTC|newest]
Thread overview: [no followups] expand[flat|nested] mbox.gz Atom feed
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=Pine.LNX.4.64.0706032039260.21792@trantor.stuart.netsweng.com \
--to=anderson@netsweng.com \
--cc=qemu-devel@nongnu.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).