Here is a refresh of the EFAULT patch. This fixes a lot of crashes in
LTP, and presumably in regular applications too. This still needs to
have the checking foldded into lock_user(), but there were a handful
of small fixes since this patch was last sent out.


                                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-26 11:18:49.000000000 -0400
+++ qemu/exec.c	2007-03-26 11:20:06.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-26 11:18:49.000000000 -0400
+++ qemu/cpu-all.h	2007-03-26 11:20:06.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-26 11:20:05.000000000 -0400
+++ qemu/linux-user/syscall.c	2007-03-26 14:11:21.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;
@@ -851,11 +869,11 @@
 {
     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) ) return -ret2;
         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);
-    long ret;
+    socklen_t addrlen;
+    void *addr;
+    long ret,ret2;
+
+    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( ret2=host_to_target_sockaddr(target_addr, addr, addrlen, PAGE_WRITE) ) return -ret2;
         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);
-    long ret;
+    socklen_t addrlen;
+    void *addr;
+    long ret,ret2;
+
+    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( ret2=host_to_target_sockaddr(target_addr, addr, addrlen, PAGE_WRITE) ) return -ret2;
         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));
@@ -930,9 +957,10 @@
     socklen_t addrlen;
     void *addr;
     void *host_msg;
-    long ret;
+    long ret,ret2;
 
     host_msg = lock_user(msg, len, 0);
+    if( ret2=page_check_range(host_msg,len,PAGE_WRITE) ) return -ret2;
     if (target_addr) {
         addrlen = tget32(target_addrlen);
         addr = alloca(addrlen);
@@ -943,7 +971,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) ) return -ret2;
             tput32(target_addrlen, addrlen);
         }
         unlock_user(host_msg, msg, len);
@@ -1150,13 +1178,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 +1196,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 +1218,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 +1270,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 +1285,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 +1319,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 +1346,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 +1400,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 +1419,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 +1441,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 +1452,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 +1479,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 +1497,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 +2777,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 +2790,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 +2802,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 +2816,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 +2833,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));
@@ -2878,6 +2962,7 @@
             ret = get_errno(sigpending(&set));
             if (!is_error(ret)) {
                 p = lock_user(arg1, sizeof(target_sigset_t), 0);
+                if( ret=page_check_range(p,sizeof(target_sigset_t),PAGE_WRITE) ) return -ret;
                 host_to_target_sigset(p, &set);
                 unlock_user(p, arg1, sizeof(target_sigset_t));
             }
@@ -3341,6 +3426,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 +3926,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 +3934,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 +3949,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 +3975,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);

Reply via email to