qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
* [Qemu-devel] [PATCH] linux-user EFAULT implementation
@ 2007-07-06 15:15 Stuart Anderson
  2007-07-06 16:08 ` Fabrice Bellard
  0 siblings, 1 reply; 13+ messages in thread
From: Stuart Anderson @ 2007-07-06 15:15 UTC (permalink / raw)
  To: qemu-devel

[-- Attachment #1: Type: TEXT/PLAIN, Size: 660 bytes --]


Here is a refresh of the linux-user EFAULT patch vs todays cvs. This
patch has now received a lot more runtime, and a couple of bug have been
fixed that affected some of the socket APIs.

The purpose of this patch is to detect bad pointers and return EFAULT
instead of just crashing when the bad pointers are used by qemu.


                                 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 patch --]
[-- Type: TEXT/x-diff, Size: 45594 bytes --]

Index: qemu/exec.c
===================================================================
--- qemu.orig/exec.c	2007-07-06 09:46:45.000000000 -0400
+++ qemu/exec.c	2007-07-06 09:49:37.000000000 -0400
@@ -1862,6 +1862,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-07-06 09:47:42.000000000 -0400
+++ qemu/cpu-all.h	2007-07-06 09:49:37.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);
 
 CPUState *cpu_copy(CPUState *env);
 
Index: qemu/linux-user/syscall.c
===================================================================
--- qemu.orig/linux-user/syscall.c	2007-07-06 09:46:45.000000000 -0400
+++ qemu/linux-user/syscall.c	2007-07-06 09:49:37.000000000 -0400
@@ -404,12 +404,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);
@@ -431,26 +432,32 @@
     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);
+
+    return ret;
 }
 
-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);
+
+    return ret;
 }
 
 
@@ -462,25 +469,25 @@
     fd_set *rfds_ptr, *wfds_ptr, *efds_ptr;
     target_long *target_rfds, *target_wfds, *target_efds;
     struct timeval tv, *tv_ptr;
-    long ret;
+    long ret,ret2;
     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;
@@ -488,7 +495,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;
@@ -502,7 +509,7 @@
         host_to_target_fds(target_efds, efds_ptr, n);
 
         if (target_tv) {
-            host_to_target_timeval(target_tv, &tv);
+            if( (ret2=host_to_target_timeval(target_tv, &tv)) != 0 ) return ret2;
         }
     }
     if (target_rfds)
@@ -515,28 +522,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?  */
@@ -897,18 +910,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));
 }
 
@@ -922,12 +937,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,13 +984,16 @@
 static long do_accept(int fd, target_ulong target_addr,
                       target_ulong target_addrlen)
 {
-    socklen_t addrlen = tget32(target_addrlen);
+    socklen_t addrlen;
     void *addr = alloca(addrlen);
-    long ret;
+    long ret,ret2;
+
+    if( (ret2=page_check_range(target_addrlen,sizeof(socklen_t),PAGE_WRITE)) != 0 ) return -EINVAL;
+    addrlen = tget32(target_addrlen);
 
     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;
         tput32(target_addrlen, addrlen);
     }
     return ret;
@@ -973,13 +1002,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;
@@ -988,13 +1022,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;
@@ -1021,10 +1059,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));
@@ -1039,9 +1077,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);
@@ -1052,7 +1090,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);
@@ -1259,13 +1297,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);
@@ -1274,15 +1314,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);
@@ -1291,32 +1335,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 {
@@ -1331,67 +1385,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)
@@ -1403,34 +1465,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));
@@ -1457,13 +1519,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);
@@ -1473,15 +1537,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);
@@ -1491,6 +1558,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)
@@ -1500,10 +1569,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));
     }
@@ -1521,7 +1595,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);
@@ -1538,7 +1612,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)
@@ -2018,6 +2092,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;
@@ -2026,7 +2101,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);
@@ -2225,7 +2300,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);
@@ -2234,6 +2309,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);
@@ -2246,7 +2322,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);
@@ -2257,7 +2333,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);
@@ -2266,7 +2342,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);
@@ -2277,7 +2353,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);
@@ -2419,23 +2495,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);
@@ -2444,7 +2523,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;
@@ -2671,7 +2750,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);
@@ -2689,9 +2768,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;
@@ -2860,7 +2939,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;
@@ -2872,7 +2951,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;
@@ -2883,7 +2962,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;
@@ -2896,7 +2975,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];
@@ -2914,12 +2993,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));
@@ -3046,7 +3127,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));
             }
@@ -3056,7 +3137,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));
@@ -3066,7 +3147,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));
@@ -3078,18 +3159,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));
             }
@@ -3098,7 +3179,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));
@@ -3153,7 +3234,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;
@@ -3162,14 +3243,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;
@@ -3488,19 +3569,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;
@@ -3510,10 +3591,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;
@@ -3534,7 +3615,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
@@ -3965,17 +4046,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;
@@ -4072,6 +4153,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;
@@ -4079,6 +4161,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;
@@ -4092,7 +4175,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);
@@ -4117,7 +4200,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);
@@ -4583,7 +4666,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;
     }
@@ -4594,7 +4677,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-07-06 09:42:29.000000000 -0400
+++ qemu/linux-user/qemu.h	2007-07-06 09:49:37.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)

^ permalink raw reply	[flat|nested] 13+ messages in thread

end of thread, other threads:[~2007-07-20 20:16 UTC | newest]

Thread overview: 13+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2007-07-06 15:15 [Qemu-devel] [PATCH] linux-user EFAULT implementation Stuart Anderson
2007-07-06 16:08 ` Fabrice Bellard
2007-07-06 16:55   ` Stuart Anderson
2007-07-06 18:45     ` Stuart Anderson
2007-07-09 11:41       ` Stuart Anderson
2007-07-09 12:02         ` Stuart Anderson
2007-07-09 21:15         ` Fabrice Bellard
2007-07-10  2:22           ` Stuart Anderson
2007-07-10 12:38             ` Paul Brook
2007-07-10 20:45               ` Fabrice Bellard
2007-07-10 21:09                 ` Stuart Anderson
2007-07-13 17:55                   ` Stuart Anderson
2007-07-20 20:16                     ` Stuart Anderson

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