Here is an updated patch that show more of the changes that are needed
to detect EFAULT situations in linux-user. The areas I focused on are
the socket, semaphore, and message queue family of syscalls as they all
make interesting use of pointers to structures. This patch does sit on
top of the other patches I sent to this list this week for semaphores
and message queues, so it can't be 'test driven' without them.

With this patch, more of the Linux Test Project test suite is able to
PASS, and qemu SEGVs less frequently.

Still to be done is to actually fold this into lock_user(), and finish
applying it in the other applicable syscalls.

Comments would be appreciated.


                                Stuart

Stuart R. Anderson                               [EMAIL PROTECTED]
Network & Software Engineering                   http://www.netsweng.com/
1024D/37A79149:                                  0791 D3B8 9A4C 2CDC A31F
                                                 BD03 0A62 E534 37A7 9149
Index: qemu/exec.c
===================================================================
--- qemu.orig/exec.c	2007-03-23 09:05:45.000000000 -0400
+++ qemu/exec.c	2007-03-23 09:06:23.000000000 -0400
@@ -1785,6 +1785,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-03-23 09:05:45.000000000 -0400
+++ qemu/cpu-all.h	2007-03-23 10:52:16.000000000 -0400
@@ -689,6 +689,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-03-23 09:06:16.000000000 -0400
+++ qemu/linux-user/syscall.c	2007-03-23 10:55:01.000000000 -0400
@@ -406,28 +406,36 @@
     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=page_check_range(target_saddr,len,pg_access) ) 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=page_check_range(target_saddr,len,pg_access) ) 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?  */
@@ -788,18 +796,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) ) 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) ) return -ret;
     return get_errno(connect(sockfd, addr, addrlen));
 }
 
@@ -814,11 +824,19 @@
     target_ulong target_vec;
 
     lock_user_struct(msgp, target_msg, 1);
+    if( send )
+       if( ret=page_check_range(msgp,sizeof(*msgp),PAGE_READ) ) return -ret;
+    else
+       if( ret=page_check_range(msgp,sizeof(*msgp),PAGE_WRITE) ) 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) ) return -ret;
+        else
+          if( ret=target_to_host_sockaddr(msg.msg_name, tswapl(msgp->msg_name),
+                                msg.msg_namelen,PAGE_WRITE) ) return -ret;
     } else {
         msg.msg_name = NULL;
         msg.msg_namelen = 0;
@@ -855,7 +873,7 @@
 
     ret = get_errno(accept(fd, addr, &addrlen));
     if (!is_error(ret)) {
-        host_to_target_sockaddr(target_addr, addr, addrlen);
+        if( ret=host_to_target_sockaddr(target_addr, addr, addrlen, PAGE_WRITE) ) return -ret;
         tput32(target_addrlen, addrlen);
     }
     return ret;
@@ -864,13 +882,17 @@
 static long do_getpeername(int fd, target_ulong target_addr,
                            target_ulong target_addrlen)
 {
-    socklen_t addrlen = tget32(target_addrlen);
-    void *addr = alloca(addrlen);
+    socklen_t addrlen;
+    void *addr;
     long ret;
 
+    if( ret=page_check_range(target_addrlen,sizeof(socklen_t),PAGE_WRITE) ) 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( ret=host_to_target_sockaddr(target_addr, addr, addrlen, PAGE_WRITE) ) return -ret;
         tput32(target_addrlen, addrlen);
     }
     return ret;
@@ -879,13 +901,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);
+    socklen_t addrlen;
+    void *addr;
     long ret;
 
+    if( ret=page_check_range(target_addrlen,sizeof(socklen_t),PAGE_WRITE) ) 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( ret=host_to_target_sockaddr(target_addr, addr, addrlen, PAGE_WRITE) ) return -ret;
         tput32(target_addrlen, addrlen);
     }
     return ret;
@@ -913,9 +939,10 @@
     long ret;
 
     host_msg = lock_user(msg, len, 1);
+    if( ret=page_check_range(host_msg,len,PAGE_READ) ) 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) ) return -ret;
         ret = get_errno(sendto(fd, host_msg, len, flags, addr, addrlen));
     } else {
         ret = get_errno(send(fd, host_msg, len, flags));
@@ -943,7 +970,7 @@
     }
     if (!is_error(ret)) {
         if (target_addr) {
-            host_to_target_sockaddr(target_addr, addr, addrlen);
+            if( ret=host_to_target_sockaddr(target_addr, addr, addrlen, PAGE_WRITE) ) return -ret;
             tput32(target_addrlen, addrlen);
         }
         unlock_user(host_msg, msg, len);
@@ -953,7 +980,7 @@
     return ret;
 }
 
-static long do_socketcall(int num, target_ulong vptr)
+/* static */ long do_socketcall(int num, target_ulong vptr)
 {
     long ret;
     const int n = sizeof(target_ulong);
@@ -1150,13 +1177,16 @@
   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=page_check_range(target_sd,sizeof(*target_sd),pg_access) ) return -ret;
     target_ip=&(target_sd->sem_perm);
     host_ip->__key = tswapl(target_ip->__key);
     host_ip->uid = tswapl(target_ip->uid);
@@ -1165,15 +1195,20 @@
     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=page_check_range(target_sd,sizeof(*target_sd),pg_access) ) return -ret;
     target_ip = &(target_sd->sem_perm);
     target_ip->__key = tswapl(host_ip->__key);
     target_ip->uid = tswapl(host_ip->uid);
@@ -1182,32 +1217,44 @@
     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=page_check_range(target_sd,sizeof(*target_sd),pg_access) ) return -ret;
+    target_to_host_ipc_perm(&(host_sd->sem_perm),target_addr,pg_access);
     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));
+    host_to_target_ipc_perm(target_addr,&(host_sd->sem_perm),pg_access);
+    if( ret=page_check_range(target_sd,sizeof(*target_sd),pg_access) ) 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 {
@@ -1222,11 +1269,13 @@
 	target_long 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 ) {
@@ -1235,26 +1284,32 @@
 	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=page_check_range(target_su,sizeof(*target_su),pg_access) ) return -ret;
+	   if( ret=target_to_host_semid_ds(ds,target_su->buf, pg_access) ) 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=page_check_range(target_su,sizeof(*target_su),pg_access) ) return -ret;
 	   host_su->val = tswapl(target_su->val);
            unlock_user_struct(target_su, target_addr, 0);
 	   break;
 	default:
 	   host_su->array = tswapl(target_su->array);
     }
+
+    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 ) {
@@ -1263,18 +1318,22 @@
 	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=page_check_range(target_su,sizeof(*target_su),pg_access) ) return -ret;
+	   if( ret=host_to_target_semid_ds(target_su->buf,ds, pg_access) ) 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=page_check_range(target_su,sizeof(*target_su),pg_access) ) return -ret;
 	   target_su->val = tswapl(host_su->val);
            unlock_user_struct(target_su, target_addr, 1);
 	   break;
         default:
 	   target_su->array = tswapl(host_su->array);
     }
+
+    return ret;
 }
 
 static inline long do_semctl(long first, long second, long third, long ptr)
@@ -1286,34 +1345,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) ) 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) ) 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) ) 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) ) 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) ) 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) ) 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));
@@ -1340,13 +1399,16 @@
   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=page_check_range(target_md,sizeof(*target_md),pg_access) ) return -ret;
+    target_to_host_ipc_perm(&(host_md->msg_perm),target_addr,pg_access);
     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);
@@ -1356,15 +1418,19 @@
     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=page_check_range(target_md,sizeof(*target_md),pg_access) ) return -ret;
+    host_to_target_ipc_perm(target_addr,&(host_md->msg_perm),pg_access);
     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);
@@ -1374,6 +1440,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)
@@ -1383,10 +1451,15 @@
     long ret = 0;
     switch( cmd ) {
     case IPC_STAT:
+        if( ret=target_to_host_msqid_ds(&dsarg,ptr,PAGE_WRITE) ) 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) ) 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));
     }
@@ -1405,6 +1478,7 @@
     long ret = 0;
 
     lock_user_struct(target_mb,msgp,0);
+    if( ret=page_check_range(target_mb,sizeof(long)+msgsz,PAGE_READ) ) return -ret;
     host_mb = malloc(msgsz+sizeof(long));
     host_mb->mtype = tswapl(target_mb->mtype);
     memcpy(host_mb->mtext,target_mb->mtext,msgsz);
@@ -1422,6 +1496,7 @@
     long ret = 0;
 
     lock_user_struct(target_mb,msgp,0);
+    if( ret=page_check_range(target_mb,sizeof(long)+msgsz,PAGE_WRITE) ) return -ret;
     host_mb = malloc(msgsz+sizeof(long));
     ret = get_errno(msgrcv(msqid, host_mb, msgsz, 1, msgflg));
     if( ret > 0 )
@@ -2701,6 +2776,7 @@
             struct target_sigaction act, oact, *pact;
             if (arg2) {
                 lock_user_struct(old_act, arg2, 1);
+                if( ret=page_check_range(old_act,sizeof(*old_act),PAGE_READ) ) 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;
@@ -2713,6 +2789,7 @@
             ret = get_errno(do_sigaction(arg1, pact, &oact));
             if (!is_error(ret) && arg3) {
                 lock_user_struct(old_act, arg3, 0);
+                if( ret=page_check_range(old_act,sizeof(*old_act),PAGE_WRITE) ) 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;
@@ -2724,6 +2801,7 @@
 
 	    if (arg2) {
 		lock_user_struct(old_act, arg2, 1);
+		if( ret=page_check_range(old_act,sizeof(*old_act),PAGE_READ) ) 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;
@@ -2737,6 +2815,7 @@
 
 	    if (!is_error(ret) && arg3) {
 		lock_user_struct(old_act, arg3, 0);
+		if( ret=page_check_range(old_act,sizeof(*old_act),PAGE_WRITE) ) 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];
@@ -2753,12 +2832,16 @@
             struct target_sigaction *act;
             struct target_sigaction *oact;
 
-            if (arg2)
+            if (arg2) {
                 lock_user_struct(act, arg2, 1);
+                if( ret=page_check_range(act,sizeof(*act),PAGE_READ) ) return -ret;
+                }
             else
                 act = NULL;
-            if (arg3)
+            if (arg3) {
                 lock_user_struct(oact, arg3, 0);
+                if( ret=page_check_range(oact,sizeof(*oact),PAGE_WRITE) ) return -ret;
+                }
             else
                 oact = NULL;
             ret = get_errno(do_sigaction(arg1, act, oact));
@@ -3341,6 +3424,7 @@
                 struct target_stat *target_st;
                 
                 lock_user_struct(target_st, arg2, 0);
+                if( ret=page_check_range(target_st,sizeof(*target_st),PAGE_WRITE) ) return -ret;
                 target_st->st_dev = tswap16(st.st_dev);
                 target_st->st_ino = tswapl(st.st_ino);
 #if defined(TARGET_PPC) || defined(TARGET_MIPS)
@@ -3840,6 +3924,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;
@@ -3847,6 +3932,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;
@@ -3861,6 +3947,7 @@
                 if (((CPUARMState *)cpu_env)->eabi) {
                     struct target_eabi_stat64 *target_st;
                     lock_user_struct(target_st, arg2, 1);
+                    if( ret=page_check_range(target_st,sizeof(*target_st),PAGE_WRITE) ) 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);
@@ -3886,6 +3973,7 @@
                 {
                     struct target_stat64 *target_st;
                     lock_user_struct(target_st, arg2, 1);
+                    if( ret=page_check_range(target_st,sizeof(*target_st),PAGE_WRITE) ) return -ret;
                     memset(target_st, 0, sizeof(struct target_stat64));
                     /* ??? put_user is probably wrong.  */
                     put_user(st.st_dev, &target_st->st_dev);
_______________________________________________
Qemu-devel mailing list
Qemu-devel@nongnu.org
http://lists.nongnu.org/mailman/listinfo/qemu-devel

Reply via email to