commit 579a97f7ff4c0f958a5d8adcba717a205bb58567
Author: bellard <bellard@c046a42c-6fe2-441c-8c8c-71466251a162>
Date:   Sun Nov 11 14:26:47 2007 +0000

    Linux user memory access API change (initial patch by Thayne Harbaugh)
    
    
    git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@3583 c046a42c-6fe2-441c-8c8c-71466251a162

diff --git a/linux-user/syscall.c b/linux-user/syscall.c
index 07e84d9..656f78e 100644
--- a/linux-user/syscall.c
+++ b/linux-user/syscall.c
@@ -504,12 +504,13 @@ static inline abi_long host_to_target_clock_t(long ticks)
 #endif
 }
 
-static inline void host_to_target_rusage(abi_ulong target_addr,
-                                         const struct rusage *rusage)
+static inline abi_long host_to_target_rusage(abi_ulong target_addr,
+                                             const struct rusage *rusage)
 {
     struct target_rusage *target_rusage;
 
-    lock_user_struct(target_rusage, target_addr, 0);
+    if (!lock_user_struct(VERIFY_WRITE, target_rusage, target_addr, 0))
+        return -TARGET_EFAULT;
     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);
@@ -529,28 +530,36 @@ static inline void host_to_target_rusage(abi_ulong target_addr,
     target_rusage->ru_nvcsw = tswapl(rusage->ru_nvcsw);
     target_rusage->ru_nivcsw = tswapl(rusage->ru_nivcsw);
     unlock_user_struct(target_rusage, target_addr, 1);
+
+    return 0;
 }
 
-static inline void target_to_host_timeval(struct timeval *tv,
-                                          abi_ulong target_addr)
+static inline abi_long target_to_host_timeval(struct timeval *tv,
+                                              abi_ulong target_addr)
 {
     struct target_timeval *target_tv;
 
-    lock_user_struct(target_tv, target_addr, 1);
+    if (!lock_user_struct(VERIFY_READ, target_tv, target_addr, 1))
+        return -TARGET_EFAULT;
     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 0;
 }
 
-static inline void host_to_target_timeval(abi_ulong target_addr,
-                                          const struct timeval *tv)
+static inline abi_long host_to_target_timeval(abi_ulong target_addr,
+                                              const struct timeval *tv)
 {
     struct target_timeval *target_tv;
 
-    lock_user_struct(target_tv, target_addr, 0);
+    if (!lock_user_struct(VERIFY_WRITE, target_tv, target_addr, 0))
+        return -TARGET_EFAULT;
     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 0;
 }
 
 
@@ -567,21 +576,33 @@ static abi_long do_select(int n,
     int ok;
 
     if (rfd_p) {
-        target_rfds = lock_user(rfd_p, sizeof(abi_long) * n, 1);
+        target_rfds = lock_user(VERIFY_WRITE, rfd_p, sizeof(abi_long) * n, 1);
+        if (!target_rfds) {
+            ret = -TARGET_EFAULT;
+            goto end;
+        }
         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(abi_long) * n, 1);
+        target_wfds = lock_user(VERIFY_WRITE, wfd_p, sizeof(abi_long) * n, 1);
+        if (!target_wfds) {
+            ret = -TARGET_EFAULT;
+            goto end;
+        }
         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(abi_long) * n, 1);
+        target_efds = lock_user(VERIFY_WRITE, efd_p, sizeof(abi_long) * n, 1);
+        if (!target_efds) {
+            ret = -TARGET_EFAULT;
+            goto end;
+        }
         efds_ptr = target_to_host_fds(&efds, target_efds, n);
     } else {
         target_efds = NULL;
@@ -606,38 +627,45 @@ static abi_long do_select(int n,
             host_to_target_timeval(target_tv, &tv);
         }
     }
-    if (target_rfds)
-        unlock_user(target_rfds, rfd_p, ok ? sizeof(abi_long) * n : 0);
-    if (target_wfds)
-        unlock_user(target_wfds, wfd_p, ok ? sizeof(abi_long) * n : 0);
-    if (target_efds)
-        unlock_user(target_efds, efd_p, ok ? sizeof(abi_long) * n : 0);
+
+end:
+    unlock_user(target_rfds, rfd_p, ok ? sizeof(abi_long) * n : 0);
+    unlock_user(target_wfds, wfd_p, ok ? sizeof(abi_long) * n : 0);
+    unlock_user(target_efds, efd_p, ok ? sizeof(abi_long) * n : 0);
 
     return ret;
 }
 
-static inline void target_to_host_sockaddr(struct sockaddr *addr,
-                                           abi_ulong target_addr,
-                                           socklen_t len)
+static inline abi_long target_to_host_sockaddr(struct sockaddr *addr,
+                                               abi_ulong target_addr,
+                                               socklen_t len)
 {
     struct target_sockaddr *target_saddr;
 
-    target_saddr = lock_user(target_addr, len, 1);
+    target_saddr = lock_user(VERIFY_READ, target_addr, len, 1);
+    if (!target_saddr)
+        return -TARGET_EFAULT;
     memcpy(addr, target_saddr, len);
     addr->sa_family = tswap16(target_saddr->sa_family);
     unlock_user(target_saddr, target_addr, 0);
+
+    return 0;
 }
 
-static inline void host_to_target_sockaddr(abi_ulong target_addr,
-                                           struct sockaddr *addr,
-                                           socklen_t len)
+static inline abi_long host_to_target_sockaddr(abi_ulong target_addr,
+                                               struct sockaddr *addr,
+                                               socklen_t len)
 {
     struct target_sockaddr *target_saddr;
 
-    target_saddr = lock_user(target_addr, len, 0);
+    target_saddr = lock_user(VERIFY_WRITE, target_addr, len, 0);
+    if (!target_saddr)
+        return -TARGET_EFAULT;
     memcpy(target_saddr, addr, len);
     target_saddr->sa_family = tswap16(addr->sa_family);
     unlock_user(target_saddr, target_addr, len);
+
+    return 0;
 }
 
 /* ??? Should this also swap msgh->name?  */
@@ -941,35 +969,56 @@ static abi_long do_getsockopt(int sockfd, int level, int optname,
     return ret;
 }
 
-static void lock_iovec(struct iovec *vec, abi_ulong target_addr,
-                       int count, int copy)
+/* FIXME
+ * lock_iovec()/unlock_iovec() have a return code of 0 for success where
+ * other lock functions have a return code of 0 for failure.
+ */
+static abi_long lock_iovec(int type, struct iovec *vec, abi_ulong target_addr,
+                           int count, int copy)
 {
     struct target_iovec *target_vec;
     abi_ulong base;
-    int i;
+    int i, j;
 
-    target_vec = lock_user(target_addr, count * sizeof(struct target_iovec), 1);
+    target_vec = lock_user(VERIFY_READ, target_addr, count * sizeof(struct target_iovec), 1);
+    if (!target_vec)
+        return -TARGET_EFAULT;
     for(i = 0;i < count; i++) {
         base = tswapl(target_vec[i].iov_base);
         vec[i].iov_len = tswapl(target_vec[i].iov_len);
-        vec[i].iov_base = lock_user(base, vec[i].iov_len, copy);
+        vec[i].iov_base = lock_user(type, base, vec[i].iov_len, copy);
+	if (!vec[i].iov_base) 
+            goto fail;
+    }
+    unlock_user (target_vec, target_addr, 0);
+    return 0;
+ fail:
+    /* failure - unwind locks */
+    for (j = 0; j < i; j++) {
+        base = tswapl(target_vec[j].iov_base);
+        unlock_user(vec[j].iov_base, base, 0);
     }
     unlock_user (target_vec, target_addr, 0);
+    return -TARGET_EFAULT;
 }
 
-static void unlock_iovec(struct iovec *vec, abi_ulong target_addr,
-                         int count, int copy)
+static abi_long unlock_iovec(struct iovec *vec, abi_ulong target_addr,
+                             int count, int copy)
 {
     struct target_iovec *target_vec;
     abi_ulong base;
     int i;
 
-    target_vec = lock_user(target_addr, count * sizeof(struct target_iovec), 1);
+    target_vec = lock_user(VERIFY_READ, target_addr, count * sizeof(struct target_iovec), 1);
+    if (!target_vec)
+        return -TARGET_EFAULT;
     for(i = 0;i < count; i++) {
         base = tswapl(target_vec[i].iov_base);
         unlock_user(vec[i].iov_base, base, copy ? vec[i].iov_len : 0);
     }
     unlock_user (target_vec, target_addr, 0);
+
+    return 0;
 }
 
 /* do_socket() Must return target values and target errnos. */
@@ -1033,7 +1082,12 @@ static abi_long do_sendrecvmsg(int fd, abi_ulong target_msg,
     struct iovec *vec;
     abi_ulong target_vec;
 
-    lock_user_struct(msgp, target_msg, 1);
+    /* FIXME */
+    if (!lock_user_struct(send ? VERIFY_READ : VERIFY_WRITE,
+                          msgp,
+                          target_msg,
+                          send ? 1 : 0))
+        return -TARGET_EFAULT;
     if (msgp->msg_name) {
         msg.msg_namelen = tswap32(msgp->msg_namelen);
         msg.msg_name = alloca(msg.msg_namelen);
@@ -1050,7 +1104,7 @@ static abi_long do_sendrecvmsg(int fd, abi_ulong target_msg,
     count = tswapl(msgp->msg_iovlen);
     vec = alloca(count * sizeof(struct iovec));
     target_vec = tswapl(msgp->msg_iov);
-    lock_iovec(vec, target_vec, count, send);
+    lock_iovec(send ? VERIFY_READ : VERIFY_WRITE, vec, target_vec, count, send);
     msg.msg_iovlen = count;
     msg.msg_iov = vec;
 
@@ -1063,6 +1117,7 @@ static abi_long do_sendrecvmsg(int fd, abi_ulong target_msg,
             host_to_target_cmsg(msgp, &msg);
     }
     unlock_iovec(vec, target_vec, count, !send);
+    unlock_user_struct(msgp, target_msg, send ? 0 : 1);
     return ret;
 }
 
@@ -1137,7 +1192,9 @@ static abi_long do_sendto(int fd, abi_ulong msg, size_t len, int flags,
     void *host_msg;
     abi_long ret;
 
-    host_msg = lock_user(msg, len, 1);
+    host_msg = lock_user(VERIFY_READ, msg, len, 1);
+    if (!host_msg)
+        return -TARGET_EFAULT;
     if (target_addr) {
         addr = alloca(addrlen);
         target_to_host_sockaddr(addr, target_addr, addrlen);
@@ -1159,7 +1216,9 @@ static abi_long do_recvfrom(int fd, abi_ulong msg, size_t len, int flags,
     void *host_msg;
     abi_long ret;
 
-    host_msg = lock_user(msg, len, 0);
+    host_msg = lock_user(VERIFY_WRITE, msg, len, 0);
+    if (!host_msg)
+        return -TARGET_EFAULT;
     if (target_addr) {
         addrlen = tget32(target_addrlen);
         addr = alloca(addrlen);
@@ -1381,13 +1440,14 @@ struct target_semid_ds
   abi_ulong __unused4;
 };
 
-static inline void target_to_host_ipc_perm(struct ipc_perm *host_ip,
-                                           abi_ulong target_addr)
+static inline abi_long target_to_host_ipc_perm(struct ipc_perm *host_ip,
+                                               abi_ulong target_addr)
 {
     struct target_ipc_perm *target_ip;
     struct target_semid_ds *target_sd;
 
-    lock_user_struct(target_sd, target_addr, 1);
+    if (!lock_user_struct(VERIFY_READ, target_sd, target_addr, 1))
+        return -TARGET_EFAULT;
     target_ip=&(target_sd->sem_perm);
     host_ip->__key = tswapl(target_ip->__key);
     host_ip->uid = tswapl(target_ip->uid);
@@ -1396,15 +1456,17 @@ static inline void target_to_host_ipc_perm(struct ipc_perm *host_ip,
     host_ip->cgid = tswapl(target_ip->cgid);
     host_ip->mode = tswapl(target_ip->mode);
     unlock_user_struct(target_sd, target_addr, 0);
+    return 0;
 }
 
-static inline void host_to_target_ipc_perm(abi_ulong target_addr,
-                                           struct ipc_perm *host_ip)
+static inline abi_long host_to_target_ipc_perm(abi_ulong target_addr,
+                                               struct ipc_perm *host_ip)
 {
     struct target_ipc_perm *target_ip;
     struct target_semid_ds *target_sd;
 
-    lock_user_struct(target_sd, target_addr, 0);
+    if (!lock_user_struct(VERIFY_WRITE, target_sd, target_addr, 0))
+        return -TARGET_EFAULT;
     target_ip = &(target_sd->sem_perm);
     target_ip->__key = tswapl(host_ip->__key);
     target_ip->uid = tswapl(host_ip->uid);
@@ -1413,32 +1475,37 @@ static inline void host_to_target_ipc_perm(abi_ulong target_addr,
     target_ip->cgid = tswapl(host_ip->cgid);
     target_ip->mode = tswapl(host_ip->mode);
     unlock_user_struct(target_sd, target_addr, 1);
+    return 0;
 }
 
-static inline void target_to_host_semid_ds(struct semid_ds *host_sd,
-                                          abi_ulong target_addr)
+static inline abi_long target_to_host_semid_ds(struct semid_ds *host_sd,
+                                               abi_ulong target_addr)
 {
     struct target_semid_ds *target_sd;
 
-    lock_user_struct(target_sd, target_addr, 1);
+    if (!lock_user_struct(VERIFY_READ, target_sd, target_addr, 1))
+        return -TARGET_EFAULT;
     target_to_host_ipc_perm(&(host_sd->sem_perm),target_addr);
     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 0;
 }
 
-static inline void host_to_target_semid_ds(abi_ulong target_addr,
-                                           struct semid_ds *host_sd)
+static inline abi_long host_to_target_semid_ds(abi_ulong target_addr,
+                                               struct semid_ds *host_sd)
 {
     struct target_semid_ds *target_sd;
 
-    lock_user_struct(target_sd, target_addr, 0);
+    if (!lock_user_struct(VERIFY_WRITE, target_sd, target_addr, 0))
+        return -TARGET_EFAULT;
     host_to_target_ipc_perm(target_addr,&(host_sd->sem_perm));
     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 0;
 }
 
 union semun {
@@ -1453,67 +1520,75 @@ union target_semun {
 	unsigned short int *array;
 };
 
-static inline void target_to_host_semun(int cmd,
-                                        union semun *host_su,
-                                        abi_ulong target_addr,
-                                        struct semid_ds *ds)
+static inline abi_long target_to_host_semun(int cmd,
+                                            union semun *host_su,
+                                            abi_ulong target_addr,
+                                            struct semid_ds *ds)
 {
     union target_semun *target_su;
 
     switch( cmd ) {
 	case IPC_STAT:
 	case IPC_SET:
-           lock_user_struct(target_su, target_addr, 1);
+           if (!lock_user_struct(VERIFY_READ, target_su, target_addr, 1))
+               return -TARGET_EFAULT;
 	   target_to_host_semid_ds(ds,target_su->buf);
 	   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 (!lock_user_struct(VERIFY_READ, target_su, target_addr, 1))
+               return -TARGET_EFAULT;
 	   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 (!lock_user_struct(VERIFY_READ, target_su, target_addr, 1))
+               return -TARGET_EFAULT;
 	   *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 0;
 }
 
-static inline void host_to_target_semun(int cmd,
-                                        abi_ulong target_addr,
-                                        union semun *host_su,
-                                        struct semid_ds *ds)
+static inline abi_long host_to_target_semun(int cmd,
+                                            abi_ulong target_addr,
+                                            union semun *host_su,
+                                            struct semid_ds *ds)
 {
     union target_semun *target_su;
 
     switch( cmd ) {
 	case IPC_STAT:
 	case IPC_SET:
-           lock_user_struct(target_su, target_addr, 0);
+           if (lock_user_struct(VERIFY_WRITE, target_su, target_addr, 0))
+               return -TARGET_EFAULT;
 	   host_to_target_semid_ds(target_su->buf,ds);
            unlock_user_struct(target_su, target_addr, 1);
 	   break;
 	case GETVAL:
 	case SETVAL:
-           lock_user_struct(target_su, target_addr, 0);
+           if (lock_user_struct(VERIFY_WRITE, target_su, target_addr, 0))
+               return -TARGET_EFAULT;
 	   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 (lock_user_struct(VERIFY_WRITE, target_su, target_addr, 0))
+               return -TARGET_EFAULT;
 	   *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 0;
 }
 
 static inline abi_long do_semctl(int first, int second, int third,
@@ -1580,12 +1655,13 @@ struct target_msqid_ds
   abi_ulong __unused5;
 };
 
-static inline void target_to_host_msqid_ds(struct msqid_ds *host_md,
-                                           abi_ulong target_addr)
+static inline abi_long target_to_host_msqid_ds(struct msqid_ds *host_md,
+                                               abi_ulong target_addr)
 {
     struct target_msqid_ds *target_md;
 
-    lock_user_struct(target_md, target_addr, 1);
+    if (!lock_user_struct(VERIFY_READ, target_md, target_addr, 1))
+        return -TARGET_EFAULT;
     target_to_host_ipc_perm(&(host_md->msg_perm),target_addr);
     host_md->msg_stime = tswapl(target_md->msg_stime);
     host_md->msg_rtime = tswapl(target_md->msg_rtime);
@@ -1596,14 +1672,16 @@ static inline void target_to_host_msqid_ds(struct msqid_ds *host_md,
     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 0;
 }
 
-static inline void host_to_target_msqid_ds(abi_ulong target_addr,
-                                           struct msqid_ds *host_md)
+static inline abi_long host_to_target_msqid_ds(abi_ulong target_addr,
+                                               struct msqid_ds *host_md)
 {
     struct target_msqid_ds *target_md;
 
-    lock_user_struct(target_md, target_addr, 0);
+    if (!lock_user_struct(VERIFY_WRITE, target_md, target_addr, 0))
+        return -TARGET_EFAULT;
     host_to_target_ipc_perm(target_addr,&(host_md->msg_perm));
     target_md->msg_stime = tswapl(host_md->msg_stime);
     target_md->msg_rtime = tswapl(host_md->msg_rtime);
@@ -1614,6 +1692,7 @@ static inline void host_to_target_msqid_ds(abi_ulong target_addr,
     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 0;
 }
 
 static inline abi_long do_msgctl(int first, int second, abi_long ptr)
@@ -1645,7 +1724,8 @@ static inline abi_long do_msgsnd(int msqid, abi_long msgp,
     struct msgbuf *host_mb;
     abi_long ret = 0;
 
-    lock_user_struct(target_mb,msgp,0);
+    if (!lock_user_struct(VERIFY_READ, target_mb, msgp, 0))
+        return -TARGET_EFAULT;
     host_mb = malloc(msgsz+sizeof(long));
     host_mb->mtype = tswapl(target_mb->mtype);
     memcpy(host_mb->mtext,target_mb->mtext,msgsz);
@@ -1661,18 +1741,30 @@ static inline abi_long do_msgrcv(int msqid, abi_long msgp,
                                  int msgflg)
 {
     struct target_msgbuf *target_mb;
+    char *target_mtext;
     struct msgbuf *host_mb;
     abi_long ret = 0;
 
-    lock_user_struct(target_mb, msgp, 0);
+    if (!lock_user_struct(VERIFY_WRITE, target_mb, msgp, 0))
+        return -TARGET_EFAULT;
     host_mb = malloc(msgsz+sizeof(long));
     ret = get_errno(msgrcv(msqid, host_mb, msgsz, 1, msgflg));
-    if (ret > 0)
+    if (ret > 0) {
+        abi_ulong target_mtext_addr = msgp + sizeof(abi_ulong);
+        target_mtext = lock_user(VERIFY_WRITE, target_mtext_addr, ret, 0);
+        if (!target_mtext) {
+            ret = -TARGET_EFAULT;
+            goto end;
+        }
     	memcpy(target_mb->mtext, host_mb->mtext, ret);
+        unlock_user(target_mtext, target_mtext_addr, ret);
+    }
     target_mb->mtype = tswapl(host_mb->mtype);
     free(host_mb);
-    unlock_user_struct(target_mb, msgp, 0);
 
+end:
+    if (target_mb)
+        unlock_user_struct(target_mb, msgp, 1);
     return ret;
 }
 
@@ -1693,7 +1785,7 @@ static abi_long do_ipc(unsigned int call, int first,
 
     switch (call) {
     case IPCOP_semop:
-        ret = get_errno(semop(first,(struct sembuf *) ptr, second));
+        ret = get_errno(semop(first,(struct sembuf *)g2h(ptr), second));
         break;
 
     case IPCOP_semget:
@@ -1723,13 +1815,14 @@ static abi_long do_ipc(unsigned int call, int first,
 
 	case IPCOP_msgrcv:
                 {
+                      /* XXX: this code is not correct */
                       struct ipc_kludge
                       {
                               void *__unbounded msgp;
                               long int msgtyp;
                       };
 
-                      struct ipc_kludge *foo = (struct ipc_kludge *) ptr;
+                      struct ipc_kludge *foo = (struct ipc_kludge *)g2h(ptr);
                       struct msgbuf *msgp = (struct msgbuf *) foo->msgp;
 
                       ret = do_msgrcv(first, (long)msgp, second, 0, third);
@@ -1761,7 +1854,7 @@ static abi_long do_ipc(unsigned int call, int first,
                 break;
 	    }
 	}
-	if (put_user(raddr, (abi_ulong *)third))
+        if (put_user(raddr, third, abi_ulong))
             return -TARGET_EFAULT;
         ret = 0;
 	break;
@@ -1883,25 +1976,33 @@ static abi_long do_ioctl(int fd, abi_long cmd, abi_long arg)
         case IOC_R:
             ret = get_errno(ioctl(fd, ie->host_cmd, buf_temp));
             if (!is_error(ret)) {
-                argptr = lock_user(arg, target_size, 0);
+                argptr = lock_user(VERIFY_WRITE, arg, target_size, 0);
+                if (!argptr)
+                    return -TARGET_EFAULT;
                 thunk_convert(argptr, buf_temp, arg_type, THUNK_TARGET);
                 unlock_user(argptr, arg, target_size);
             }
             break;
         case IOC_W:
-            argptr = lock_user(arg, target_size, 1);
+            argptr = lock_user(VERIFY_READ, arg, target_size, 1);
+            if (!argptr)
+                return -TARGET_EFAULT;
             thunk_convert(buf_temp, argptr, arg_type, THUNK_HOST);
             unlock_user(argptr, arg, 0);
             ret = get_errno(ioctl(fd, ie->host_cmd, buf_temp));
             break;
         default:
         case IOC_RW:
-            argptr = lock_user(arg, target_size, 1);
+            argptr = lock_user(VERIFY_READ, arg, target_size, 1);
+            if (!argptr)
+                return -TARGET_EFAULT;
             thunk_convert(buf_temp, argptr, arg_type, THUNK_HOST);
             unlock_user(argptr, arg, 0);
             ret = get_errno(ioctl(fd, ie->host_cmd, buf_temp));
             if (!is_error(ret)) {
-                argptr = lock_user(arg, target_size, 0);
+                argptr = lock_user(VERIFY_WRITE, arg, target_size, 0);
+                if (!argptr)
+                    return -TARGET_EFAULT;
                 thunk_convert(argptr, buf_temp, arg_type, THUNK_TARGET);
                 unlock_user(argptr, arg, target_size);
             }
@@ -2138,8 +2239,10 @@ static int read_ldt(abi_ulong ptr, unsigned long bytecount)
     size = TARGET_LDT_ENTRIES * TARGET_LDT_ENTRY_SIZE;
     if (size > bytecount)
         size = bytecount;
-    p = lock_user(ptr, size, 0);
-    /* ??? Shoudl this by byteswapped?  */
+    p = lock_user(VERIFY_WRITE, ptr, size, 0);
+    if (!p)
+        return -EFAULT;
+    /* ??? Should this by byteswapped?  */
     memcpy(p, ldt_table, size);
     unlock_user(p, ptr, size);
     return size;
@@ -2158,7 +2261,8 @@ static int write_ldt(CPUX86State *env,
 
     if (bytecount != sizeof(ldt_info))
         return -EINVAL;
-    lock_user_struct(target_ldt_info, ptr, 1);
+    if (!lock_user_struct(VERIFY_READ, target_ldt_info, ptr, 1))
+        return -EFAULT;
     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);
@@ -2365,7 +2469,8 @@ static abi_long do_fcntl(int fd, int cmd, abi_ulong arg)
 
     switch(cmd) {
     case TARGET_F_GETLK:
-        lock_user_struct(target_fl, arg, 1);
+        if (!lock_user_struct(VERIFY_READ, target_fl, arg, 1))
+            return -TARGET_EFAULT;
         fl.l_type = tswap16(target_fl->l_type);
         fl.l_whence = tswap16(target_fl->l_whence);
         fl.l_start = tswapl(target_fl->l_start);
@@ -2374,7 +2479,8 @@ static abi_long do_fcntl(int fd, int cmd, abi_ulong arg)
         unlock_user_struct(target_fl, arg, 0);
         ret = fcntl(fd, cmd, &fl);
         if (ret == 0) {
-            lock_user_struct(target_fl, arg, 0);
+            if (!lock_user_struct(VERIFY_WRITE, target_fl, arg, 0))
+                return -TARGET_EFAULT;
             target_fl->l_type = tswap16(fl.l_type);
             target_fl->l_whence = tswap16(fl.l_whence);
             target_fl->l_start = tswapl(fl.l_start);
@@ -2386,7 +2492,8 @@ static abi_long do_fcntl(int fd, int cmd, abi_ulong arg)
 
     case TARGET_F_SETLK:
     case TARGET_F_SETLKW:
-        lock_user_struct(target_fl, arg, 1);
+        if (!lock_user_struct(VERIFY_READ, target_fl, arg, 1))
+            return -TARGET_EFAULT;
         fl.l_type = tswap16(target_fl->l_type);
         fl.l_whence = tswap16(target_fl->l_whence);
         fl.l_start = tswapl(target_fl->l_start);
@@ -2397,7 +2504,8 @@ static abi_long do_fcntl(int fd, int cmd, abi_ulong arg)
         break;
 
     case TARGET_F_GETLK64:
-        lock_user_struct(target_fl64, arg, 1);
+        if (!lock_user_struct(VERIFY_READ, target_fl64, arg, 1))
+            return -TARGET_EFAULT;
         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);
@@ -2406,7 +2514,8 @@ static abi_long do_fcntl(int fd, int cmd, abi_ulong arg)
         unlock_user_struct(target_fl64, arg, 0);
         ret = fcntl(fd, cmd >> 1, &fl64);
         if (ret == 0) {
-            lock_user_struct(target_fl64, arg, 0);
+            if (!lock_user_struct(VERIFY_WRITE, target_fl64, arg, 0))
+                return -TARGET_EFAULT;
             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);
@@ -2417,14 +2526,15 @@ static abi_long do_fcntl(int fd, int cmd, abi_ulong arg)
 		break;
     case TARGET_F_SETLK64:
     case TARGET_F_SETLKW64:
-        lock_user_struct(target_fl64, arg, 1);
+        if (!lock_user_struct(VERIFY_READ, target_fl64, arg, 1))
+            return -TARGET_EFAULT;
         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);
         fl64.l_len = tswapl(target_fl64->l_len);
         fl64.l_pid = tswap16(target_fl64->l_pid);
         unlock_user_struct(target_fl64, arg, 0);
-		ret = fcntl(fd, cmd >> 1, &fl64);
+        ret = fcntl(fd, cmd >> 1, &fl64);
         break;
 
     case F_GETFL:
@@ -2577,23 +2687,25 @@ static inline abi_long target_ftruncate64(void *cpu_env, abi_long arg1,
 }
 #endif
 
-static inline void target_to_host_timespec(struct timespec *host_ts,
-                                           abi_ulong target_addr)
+static inline abi_long target_to_host_timespec(struct timespec *host_ts,
+                                               abi_ulong target_addr)
 {
     struct target_timespec *target_ts;
 
-    lock_user_struct(target_ts, target_addr, 1);
+    if (!lock_user_struct(VERIFY_READ, target_ts, target_addr, 1))
+        return -TARGET_EFAULT;
     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(abi_ulong target_addr,
-                                           struct timespec *host_ts)
+static inline abi_long host_to_target_timespec(abi_ulong target_addr,
+                                               struct timespec *host_ts)
 {
     struct target_timespec *target_ts;
 
-    lock_user_struct(target_ts, target_addr, 0);
+    if (!lock_user_struct(VERIFY_WRITE, target_ts, target_addr, 0))
+        return -TARGET_EFAULT;
     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);
@@ -2629,17 +2741,22 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
         break;
     case TARGET_NR_read:
         page_unprotect_range(arg2, arg3);
-        p = lock_user(arg2, arg3, 0);
+        if (!(p = lock_user(VERIFY_WRITE, arg2, arg3, 0)))
+            goto efault;
         ret = get_errno(read(arg1, p, arg3));
         unlock_user(p, arg2, ret);
         break;
     case TARGET_NR_write:
-        p = lock_user(arg2, arg3, 1);
+        if (!(p = lock_user(VERIFY_READ, arg2, arg3, 1)))
+            goto efault;
         ret = get_errno(write(arg1, p, arg3));
         unlock_user(p, arg2, 0);
         break;
     case TARGET_NR_open:
-        p = lock_user_string(arg1);
+        if (!(p = lock_user_string(arg1))) {
+            return -TARGET_EFAULT;
+            goto fail;
+        }
         ret = get_errno(open(path(p),
                              target_to_host_bitmask(arg2, fcntl_flags_tbl),
                              arg3));
@@ -2647,21 +2764,13 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
         break;
 #if defined(TARGET_NR_openat) && defined(__NR_openat)
     case TARGET_NR_openat:
-        if (!arg2) {
-            ret = -TARGET_EFAULT;
-            goto fail;
-        }
-        p = lock_user_string(arg2);
-        if (!access_ok(VERIFY_READ, p, 1))
-            /* Don't "goto fail" so that cleanup can happen. */
-            ret = -TARGET_EFAULT;
-        else
-            ret = get_errno(sys_openat(arg1,
-                                       path(p),
-                                       target_to_host_bitmask(arg3, fcntl_flags_tbl),
-                                       arg4));
-        if (p)
-            unlock_user(p, arg2, 0);
+        if (!(p = lock_user_string(arg2)))
+            goto efault;
+        ret = get_errno(sys_openat(arg1,
+                                   path(p),
+                                   target_to_host_bitmask(arg3, fcntl_flags_tbl),
+                                   arg4));
+        unlock_user(p, arg2, 0);
         break;
 #endif
     case TARGET_NR_close:
@@ -2685,7 +2794,8 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
 #endif
 #ifdef TARGET_NR_creat /* not on alpha */
     case TARGET_NR_creat:
-        p = lock_user_string(arg1);
+        if (!(p = lock_user_string(arg1)))
+            goto efault;
         ret = get_errno(creat(p, arg2));
         unlock_user(p, arg1, 0);
         break;
@@ -2695,54 +2805,43 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
             void * p2;
             p = lock_user_string(arg1);
             p2 = lock_user_string(arg2);
-            ret = get_errno(link(p, p2));
+            if (!p || !p2)
+                ret = -TARGET_EFAULT;
+            else
+                ret = get_errno(link(p, p2));
             unlock_user(p2, arg2, 0);
             unlock_user(p, arg1, 0);
         }
         break;
 #if defined(TARGET_NR_linkat) && defined(__NR_linkat)
     case TARGET_NR_linkat:
-        if (!arg2 || !arg4) {
-            ret = -TARGET_EFAULT;
-            goto fail;
-        }
         {
             void * p2 = NULL;
+            if (!arg2 || !arg4)
+                goto efault;
             p  = lock_user_string(arg2);
             p2 = lock_user_string(arg4);
-            if (!access_ok(VERIFY_READ, p, 1)
-                || !access_ok(VERIFY_READ, p2, 1))
-                /* Don't "goto fail" so that cleanup can happen. */
+            if (!p || !p2)
                 ret = -TARGET_EFAULT;
             else
                 ret = get_errno(sys_linkat(arg1, p, arg3, p2, arg5));
-            if (p2)
-                unlock_user(p, arg2, 0);
-            if (p)
-                unlock_user(p2, arg4, 0);
+            unlock_user(p, arg2, 0);
+            unlock_user(p2, arg4, 0);
         }
         break;
 #endif
     case TARGET_NR_unlink:
-        p = lock_user_string(arg1);
+        if (!(p = lock_user_string(arg1)))
+            goto efault;
         ret = get_errno(unlink(p));
         unlock_user(p, arg1, 0);
         break;
 #if defined(TARGET_NR_unlinkat) && defined(__NR_unlinkat)
     case TARGET_NR_unlinkat:
-        if (!arg2) {
-            ret = -TARGET_EFAULT;
-            goto fail;
-        }
-        p = lock_user_string(arg2);
-        if (!access_ok(VERIFY_READ, p, 1))
-            /* Don't "goto fail" so that cleanup can happen. */
-            ret = -TARGET_EFAULT;
-        else
-            ret = get_errno(sys_unlinkat(arg1, p, arg3));
-        if (p)
-            unlock_user(p, arg2, 0);
-        break;
+        if (!(p = lock_user_string(arg2)))
+            goto efault;
+        ret = get_errno(sys_unlinkat(arg1, p, arg3));
+        unlock_user(p, arg2, 0);
 #endif
     case TARGET_NR_execve:
         {
@@ -2771,7 +2870,10 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
                 addr = tgetl(gp);
                 if (!addr)
                     break;
-                *q = lock_user_string(addr);
+                if (!(*q = lock_user_string(addr))) {
+                    ret = -TARGET_EFAULT;
+                    goto execve_fail;
+                }
             }
             *q = NULL;
 
@@ -2780,14 +2882,21 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
                 addr = tgetl(gp);
                 if (!addr)
                     break;
-                *q = lock_user_string(addr);
+                if (!(*q = lock_user_string(addr))) {
+                    ret = -TARGET_EFAULT;
+                    goto execve_fail;
+                }
             }
             *q = NULL;
 
-            p = lock_user_string(arg1);
+            if (!(p = lock_user_string(arg1))) {
+                ret = -TARGET_EFAULT;
+                goto execve_fail;
+            }
             ret = get_errno(execve(p, argp, envp));
             unlock_user(p, arg1, 0);
 
+        execve_fail:
             for (gp = guest_argp, q = argp; *q;
                   gp += sizeof(abi_ulong), q++) {
                 addr = tgetl(gp);
@@ -2801,7 +2910,8 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
         }
         break;
     case TARGET_NR_chdir:
-        p = lock_user_string(arg1);
+        if (!(p = lock_user_string(arg1)))
+            goto efault;
         ret = get_errno(chdir(p));
         unlock_user(p, arg1, 0);
         break;
@@ -2816,28 +2926,22 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
         break;
 #endif
     case TARGET_NR_mknod:
-        p = lock_user_string(arg1);
+        if (!(p = lock_user_string(arg1)))
+            goto efault;
         ret = get_errno(mknod(p, arg2, arg3));
         unlock_user(p, arg1, 0);
         break;
 #if defined(TARGET_NR_mknodat) && defined(__NR_mknodat)
     case TARGET_NR_mknodat:
-        if (!arg2) {
-            ret = -TARGET_EFAULT;
-            goto fail;
-        }
-        p = lock_user_string(arg2);
-        if (!access_ok(VERIFY_READ, p, 1))
-            /* Don't "goto fail" so that cleanup can happen. */
-            ret = -TARGET_EFAULT;
-        else
-            ret = get_errno(sys_mknodat(arg1, p, arg3, arg4));
-        if (p)
-            unlock_user(p, arg2, 0);
+        if (!(p = lock_user_string(arg2)))
+            goto efault;
+        ret = get_errno(sys_mknodat(arg1, p, arg3, arg4));
+        unlock_user(p, arg2, 0);
         break;
 #endif
     case TARGET_NR_chmod:
-        p = lock_user_string(arg1);
+        if (!(p = lock_user_string(arg1)))
+            goto efault;
         ret = get_errno(chmod(p, arg2));
         unlock_user(p, arg1, 0);
         break;
@@ -2866,15 +2970,23 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
 			p = lock_user_string(arg1);
 			p2 = lock_user_string(arg2);
 			p3 = lock_user_string(arg3);
-			ret = get_errno(mount(p, p2, p3, (unsigned long)arg4, (const void *)arg5));
-			unlock_user(p, arg1, 0);
-			unlock_user(p2, arg2, 0);
-			unlock_user(p3, arg3, 0);
+                        if (!p || !p2 || !p3)
+                            ret = -TARGET_EFAULT;
+                        else
+                            /* FIXME - arg5 should be locked, but it isn't clear how to
+                             * do that since it's not guaranteed to be a NULL-terminated
+                             * string.
+                             */
+                            ret = get_errno(mount(p, p2, p3, (unsigned long)arg4, g2h(arg5)));
+                        unlock_user(p, arg1, 0);
+                        unlock_user(p2, arg2, 0);
+                        unlock_user(p3, arg3, 0);
 			break;
 		}
 #ifdef TARGET_NR_umount
     case TARGET_NR_umount:
-        p = lock_user_string(arg1);
+        if (!(p = lock_user_string(arg1)))
+            goto efault;
         ret = get_errno(umount(p));
         unlock_user(p, arg1, 0);
         break;
@@ -2910,7 +3022,8 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
             struct utimbuf tbuf, *host_tbuf;
             struct target_utimbuf *target_tbuf;
             if (arg2) {
-                lock_user_struct(target_tbuf, arg2, 1);
+                if (!lock_user_struct(VERIFY_READ, target_tbuf, arg2, 1))
+                    goto efault;
                 tbuf.actime = tswapl(target_tbuf->actime);
                 tbuf.modtime = tswapl(target_tbuf->modtime);
                 unlock_user_struct(target_tbuf, arg2, 0);
@@ -2918,7 +3031,8 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
             } else {
                 host_tbuf = NULL;
             }
-            p = lock_user_string(arg1);
+            if (!(p = lock_user_string(arg1)))
+                goto efault;
             ret = get_errno(utime(p, host_tbuf));
             unlock_user(p, arg1, 0);
         }
@@ -2935,7 +3049,8 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
             } else {
                 tvp = NULL;
             }
-            p = lock_user_string(arg1);
+            if (!(p = lock_user_string(arg1)))
+                goto efault;
             ret = get_errno(utimes(p, tvp));
             unlock_user(p, arg1, 0);
         }
@@ -2949,24 +3064,17 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
         goto unimplemented;
 #endif
     case TARGET_NR_access:
-        p = lock_user_string(arg1);
+        if (!(p = lock_user_string(arg1)))
+            goto efault;
         ret = get_errno(access(p, arg2));
         unlock_user(p, arg1, 0);
         break;
 #if defined(TARGET_NR_faccessat) && defined(__NR_faccessat)
     case TARGET_NR_faccessat:
-        if (!arg2) {
-            ret = -TARGET_EFAULT;
-            goto fail;
-        }
-        p = lock_user_string(arg2);
-        if (!access_ok(VERIFY_READ, p, 1))
-            /* Don't "goto fail" so that cleanup can happen. */
-    	    ret = -TARGET_EFAULT;
-        else
-            ret = get_errno(sys_faccessat(arg1, p, arg3, arg4));
-        if (p)
-            unlock_user(p, arg2, 0);
+        if (!(p = lock_user_string(arg2)))
+            goto efault;
+        ret = get_errno(sys_faccessat(arg1, p, arg3, arg4));
+        unlock_user(p, arg2, 0);
         break;
 #endif
 #ifdef TARGET_NR_nice /* not on alpha */
@@ -2990,57 +3098,46 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
             void *p2;
             p = lock_user_string(arg1);
             p2 = lock_user_string(arg2);
-            ret = get_errno(rename(p, p2));
+            if (!p || !p2)
+                ret = -TARGET_EFAULT;
+            else
+                ret = get_errno(rename(p, p2));
             unlock_user(p2, arg2, 0);
             unlock_user(p, arg1, 0);
         }
         break;
 #if defined(TARGET_NR_renameat) && defined(__NR_renameat)
     case TARGET_NR_renameat:
-        if (!arg2 || !arg4) {
-            ret = -TARGET_EFAULT;
-            goto fail;
-        }
         {
-            void *p2 = NULL;
+            void *p2;
             p  = lock_user_string(arg2);
             p2 = lock_user_string(arg4);
-            if (!access_ok(VERIFY_READ, p, 1)
-                || !access_ok(VERIFY_READ, p2, 1))
-                /* Don't "goto fail" so that cleanup can happen. */
+            if (!p || !p2)
                 ret = -TARGET_EFAULT;
             else
                 ret = get_errno(sys_renameat(arg1, p, arg3, p2));
-            if (p2)
-                unlock_user(p2, arg4, 0);
-            if (p)
-                unlock_user(p, arg2, 0);
+            unlock_user(p2, arg4, 0);
+            unlock_user(p, arg2, 0);
         }
         break;
 #endif
     case TARGET_NR_mkdir:
-        p = lock_user_string(arg1);
+        if (!(p = lock_user_string(arg1)))
+            goto efault;
         ret = get_errno(mkdir(p, arg2));
         unlock_user(p, arg1, 0);
         break;
 #if defined(TARGET_NR_mkdirat) && defined(__NR_mkdirat)
     case TARGET_NR_mkdirat:
-        if (!arg2) {
-            ret = -TARGET_EFAULT;
-            goto fail;
-        }
-        p = lock_user_string(arg2);
-        if (!access_ok(VERIFY_READ, p, 1))
-            /* Don't "goto fail" so that cleanup can happen. */
-            ret = -TARGET_EFAULT;
-        else
-            ret = get_errno(sys_mkdirat(arg1, p, arg3));
-        if (p)
-            unlock_user(p, arg2, 0);
+        if (!(p = lock_user_string(arg2)))
+            goto efault;
+        ret = get_errno(sys_mkdirat(arg1, p, arg3));
+        unlock_user(p, arg2, 0);
         break;
 #endif
     case TARGET_NR_rmdir:
-        p = lock_user_string(arg1);
+        if (!(p = lock_user_string(arg1)))
+            goto efault;
         ret = get_errno(rmdir(p));
         unlock_user(p, arg1, 0);
         break;
@@ -3069,7 +3166,9 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
             struct tms tms;
             ret = get_errno(times(&tms));
             if (arg1) {
-                tmsp = lock_user(arg1, sizeof(struct target_tms), 0);
+                tmsp = lock_user(VERIFY_WRITE, arg1, sizeof(struct target_tms), 0);
+                if (!tmsp)
+                    goto efault;
                 tmsp->tms_utime = tswapl(host_to_target_clock_t(tms.tms_utime));
                 tmsp->tms_stime = tswapl(host_to_target_clock_t(tms.tms_stime));
                 tmsp->tms_cutime = tswapl(host_to_target_clock_t(tms.tms_cutime));
@@ -3088,13 +3187,15 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
         goto unimplemented;
 #endif
     case TARGET_NR_acct:
-        p = lock_user_string(arg1);
+        if (!(p = lock_user_string(arg1)))
+            goto efault;
         ret = get_errno(acct(path(p)));
         unlock_user(p, arg1, 0);
         break;
 #ifdef TARGET_NR_umount2 /* not on alpha */
     case TARGET_NR_umount2:
-        p = lock_user_string(arg1);
+        if (!(p = lock_user_string(arg1)))
+            goto efault;
         ret = get_errno(umount2(p, arg2));
         unlock_user(p, arg1, 0);
         break;
@@ -3128,7 +3229,8 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
         ret = get_errno(umask(arg1));
         break;
     case TARGET_NR_chroot:
-        p = lock_user_string(arg1);
+        if (!(p = lock_user_string(arg1)))
+            goto efault;
         ret = get_errno(chroot(p));
         unlock_user(p, arg1, 0);
         break;
@@ -3155,7 +3257,8 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
             struct target_old_sigaction *old_act;
             struct target_sigaction act, oact, *pact;
             if (arg2) {
-                lock_user_struct(old_act, arg2, 1);
+                if (!lock_user_struct(VERIFY_READ, old_act, arg2, 1))
+                    goto efault;
                 act._sa_handler = old_act->_sa_handler;
                 target_siginitset(&act.sa_mask, old_act->sa_mask);
                 act.sa_flags = old_act->sa_flags;
@@ -3167,7 +3270,8 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
             }
             ret = get_errno(do_sigaction(arg1, pact, &oact));
             if (!is_error(ret) && arg3) {
-                lock_user_struct(old_act, arg3, 0);
+                if (!lock_user_struct(VERIFY_WRITE, old_act, arg3, 0))
+                    goto efault;
                 old_act->_sa_handler = oact._sa_handler;
                 old_act->sa_mask = oact.sa_mask.sig[0];
                 old_act->sa_flags = oact.sa_flags;
@@ -3178,7 +3282,8 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
 	    struct target_sigaction act, oact, *pact, *old_act;
 
 	    if (arg2) {
-		lock_user_struct(old_act, arg2, 1);
+                if (!lock_user_struct(VERIFY_READ, old_act, arg2, 1))
+                    goto efault;
 		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;
@@ -3191,7 +3296,8 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
 	    ret = get_errno(do_sigaction(arg1, pact, &oact));
 
 	    if (!is_error(ret) && arg3) {
-		lock_user_struct(old_act, arg3, 0);
+                if (!lock_user_struct(VERIFY_WRITE, old_act, arg3, 0))
+                    goto efault;
 		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];
@@ -3209,18 +3315,23 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
             struct target_sigaction *act;
             struct target_sigaction *oact;
 
-            if (arg2)
-                lock_user_struct(act, arg2, 1);
-            else
+            if (arg2) {
+                if (!lock_user_struct(VERIFY_READ, act, arg2, 1))
+                    goto efault;
+            } else
                 act = NULL;
-            if (arg3)
-                lock_user_struct(oact, arg3, 0);
-            else
+            if (arg3) {
+                if (!lock_user_struct(VERIFY_WRITE, oact, arg3, 0)) {
+                    ret = -TARGET_EFAULT;
+                    goto rt_sigaction_fail;
+                }
+            } else
                 oact = NULL;
             ret = get_errno(do_sigaction(arg1, act, oact));
-            if (arg2)
+	rt_sigaction_fail:
+            if (act)
                 unlock_user_struct(act, arg2, 0);
-            if (arg3)
+            if (oact)
                 unlock_user_struct(oact, arg3, 1);
         }
         break;
@@ -3270,7 +3381,8 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
                     ret = -TARGET_EINVAL;
                     goto fail;
                 }
-                p = lock_user(arg2, sizeof(target_sigset_t), 1);
+                if (!(p = lock_user(VERIFY_READ, arg2, sizeof(target_sigset_t), 1)))
+                    goto efault;
                 target_to_host_old_sigset(&set, p);
                 unlock_user(p, arg2, 0);
                 set_ptr = &set;
@@ -3280,7 +3392,8 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
             }
             ret = get_errno(sigprocmask(arg1, set_ptr, &oldset));
             if (!is_error(ret) && arg3) {
-                p = lock_user(arg3, sizeof(target_sigset_t), 0);
+                if (!(p = lock_user(VERIFY_WRITE, arg3, sizeof(target_sigset_t), 0)))
+                    goto efault;
                 host_to_target_old_sigset(p, &oldset);
                 unlock_user(p, arg3, sizeof(target_sigset_t));
             }
@@ -3307,7 +3420,8 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
                     ret = -TARGET_EINVAL;
                     goto fail;
                 }
-                p = lock_user(arg2, sizeof(target_sigset_t), 1);
+                if (!(p = lock_user(VERIFY_READ, arg2, sizeof(target_sigset_t), 1)))
+                    goto efault;
                 target_to_host_sigset(&set, p);
                 unlock_user(p, arg2, 0);
                 set_ptr = &set;
@@ -3317,7 +3431,8 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
             }
             ret = get_errno(sigprocmask(how, set_ptr, &oldset));
             if (!is_error(ret) && arg3) {
-                p = lock_user(arg3, sizeof(target_sigset_t), 0);
+                if (!(p = lock_user(VERIFY_WRITE, arg3, sizeof(target_sigset_t), 0)))
+                    goto efault;
                 host_to_target_sigset(p, &oldset);
                 unlock_user(p, arg3, sizeof(target_sigset_t));
             }
@@ -3329,7 +3444,8 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
             sigset_t set;
             ret = get_errno(sigpending(&set));
             if (!is_error(ret)) {
-                p = lock_user(arg1, sizeof(target_sigset_t), 0);
+                if (!(p = lock_user(VERIFY_WRITE, arg1, sizeof(target_sigset_t), 0)))
+                    goto efault;
                 host_to_target_old_sigset(p, &set);
                 unlock_user(p, arg1, sizeof(target_sigset_t));
             }
@@ -3341,7 +3457,8 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
             sigset_t set;
             ret = get_errno(sigpending(&set));
             if (!is_error(ret)) {
-                p = lock_user(arg1, sizeof(target_sigset_t), 0);
+                if (!(p = lock_user(VERIFY_WRITE, arg1, sizeof(target_sigset_t), 0)))
+                    goto efault;
                 host_to_target_sigset(p, &set);
                 unlock_user(p, arg1, sizeof(target_sigset_t));
             }
@@ -3351,7 +3468,8 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
     case TARGET_NR_sigsuspend:
         {
             sigset_t set;
-            p = lock_user(arg1, sizeof(target_sigset_t), 1);
+            if (!(p = lock_user(VERIFY_READ, arg1, sizeof(target_sigset_t), 1)))
+                goto efault;
             target_to_host_old_sigset(&set, p);
             unlock_user(p, arg1, 0);
             ret = get_errno(sigsuspend(&set));
@@ -3361,7 +3479,8 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
     case TARGET_NR_rt_sigsuspend:
         {
             sigset_t set;
-            p = lock_user(arg1, sizeof(target_sigset_t), 1);
+            if (!(p = lock_user(VERIFY_READ, arg1, sizeof(target_sigset_t), 1)))
+                goto efault;
             target_to_host_sigset(&set, p);
             unlock_user(p, arg1, 0);
             ret = get_errno(sigsuspend(&set));
@@ -3373,7 +3492,8 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
             struct timespec uts, *puts;
             siginfo_t uinfo;
 
-            p = lock_user(arg1, sizeof(target_sigset_t), 1);
+            if (!(p = lock_user(VERIFY_READ, arg1, sizeof(target_sigset_t), 1)))
+                goto efault;
             target_to_host_sigset(&set, p);
             unlock_user(p, arg1, 0);
             if (arg3) {
@@ -3384,7 +3504,8 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
             }
             ret = get_errno(sigtimedwait(&set, &uinfo, puts));
             if (!is_error(ret) && arg2) {
-                p = lock_user(arg2, sizeof(target_sigset_t), 0);
+                if (!(p = lock_user(VERIFY_WRITE, arg2, sizeof(target_sigset_t), 0)))
+                    goto efault;
                 host_to_target_siginfo(p, &uinfo);
                 unlock_user(p, arg2, sizeof(target_sigset_t));
             }
@@ -3393,7 +3514,8 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
     case TARGET_NR_rt_sigqueueinfo:
         {
             siginfo_t uinfo;
-            p = lock_user(arg3, sizeof(target_sigset_t), 1);
+            if (!(p = lock_user(VERIFY_READ, arg3, sizeof(target_sigset_t), 1)))
+                goto efault;
             target_to_host_siginfo(&uinfo, p);
             unlock_user(p, arg1, 0);
             ret = get_errno(sys_rt_sigqueueinfo(arg1, arg2, &uinfo));
@@ -3410,7 +3532,8 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
         ret = do_rt_sigreturn(cpu_env);
         break;
     case TARGET_NR_sethostname:
-        p = lock_user_string(arg1);
+        if (!(p = lock_user_string(arg1)))
+            goto efault;
         ret = get_errno(sethostname(p, arg2));
         unlock_user(p, arg1, 0);
         break;
@@ -3420,7 +3543,8 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
             int resource = arg1;
             struct target_rlimit *target_rlim;
             struct rlimit rlim;
-            lock_user_struct(target_rlim, arg2, 1);
+            if (!lock_user_struct(VERIFY_READ, target_rlim, arg2, 1))
+                goto efault;
             rlim.rlim_cur = tswapl(target_rlim->rlim_cur);
             rlim.rlim_max = tswapl(target_rlim->rlim_max);
             unlock_user_struct(target_rlim, arg2, 0);
@@ -3436,7 +3560,8 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
 
             ret = get_errno(getrlimit(resource, &rlim));
             if (!is_error(ret)) {
-                lock_user_struct(target_rlim, arg2, 0);
+                if (!lock_user_struct(VERIFY_WRITE, target_rlim, arg2, 0))
+                    goto efault;
                 rlim.rlim_cur = tswapl(target_rlim->rlim_cur);
                 rlim.rlim_max = tswapl(target_rlim->rlim_max);
                 unlock_user_struct(target_rlim, arg2, 1);
@@ -3475,7 +3600,8 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
             abi_ulong inp, outp, exp, tvp;
             long nsel;
 
-            lock_user_struct(sel, arg1, 1);
+            if (!lock_user_struct(VERIFY_READ, sel, arg1, 1))
+                goto efault;
             nsel = tswapl(sel->n);
             inp = tswapl(sel->inp);
             outp = tswapl(sel->outp);
@@ -3491,31 +3617,26 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
             void *p2;
             p = lock_user_string(arg1);
             p2 = lock_user_string(arg2);
-            ret = get_errno(symlink(p, p2));
+            if (!p || !p2)
+                ret = -TARGET_EFAULT;
+            else
+                ret = get_errno(symlink(p, p2));
             unlock_user(p2, arg2, 0);
             unlock_user(p, arg1, 0);
         }
         break;
 #if defined(TARGET_NR_symlinkat) && defined(__NR_symlinkat)
     case TARGET_NR_symlinkat:
-        if (!arg1 || !arg3) {
-            ret = -TARGET_EFAULT;
-            goto fail;
-        }
         {
-            void *p2 = NULL;
+            void *p2;
             p  = lock_user_string(arg1);
             p2 = lock_user_string(arg3);
-            if (!access_ok(VERIFY_READ, p, 1)
-                || !access_ok(VERIFY_READ, p2, 1))
-                /* Don't "goto fail" so that cleanup can happen. */
+            if (!p || !p2)
                 ret = -TARGET_EFAULT;
             else
                 ret = get_errno(sys_symlinkat(p, arg2, p2));
-            if (p2)
-                unlock_user(p2, arg3, 0);
-            if (p)
-                unlock_user(p, arg1, 0);
+            unlock_user(p2, arg3, 0);
+            unlock_user(p, arg1, 0);
         }
         break;
 #endif
@@ -3527,32 +3648,27 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
         {
             void *p2;
             p = lock_user_string(arg1);
-            p2 = lock_user(arg2, arg3, 0);
-            ret = get_errno(readlink(path(p), p2, arg3));
+            p2 = lock_user(VERIFY_WRITE, arg2, arg3, 0);
+            if (!p || !p2)
+                ret = -TARGET_EFAULT;
+            else
+                ret = get_errno(readlink(path(p), p2, arg3));
             unlock_user(p2, arg2, ret);
             unlock_user(p, arg1, 0);
         }
         break;
 #if defined(TARGET_NR_readlinkat) && defined(__NR_readlinkat)
     case TARGET_NR_readlinkat:
-        if (!arg2 || !arg3) {
-            ret = -TARGET_EFAULT;
-            goto fail;
-        }
         {
-            void *p2 = NULL;
+            void *p2;
             p  = lock_user_string(arg2);
-            p2 = lock_user(arg3, arg4, 0);
-            if (!access_ok(VERIFY_READ, p, 1)
-                || !access_ok(VERIFY_READ, p2, 1))
-                /* Don't "goto fail" so that cleanup can happen. */
+            p2 = lock_user(VERIFY_WRITE, arg3, arg4, 0);
+            if (!p || !p2)
         	ret = -TARGET_EFAULT;
             else
                 ret = get_errno(sys_readlinkat(arg1, path(p), p2, arg4));
-            if (p2)
-                unlock_user(p2, arg3, ret);
-            if (p)
-                unlock_user(p, arg2, 0);
+            unlock_user(p2, arg3, ret);
+            unlock_user(p, arg2, 0);
         }
         break;
 #endif
@@ -3562,7 +3678,8 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
 #endif
 #ifdef TARGET_NR_swapon
     case TARGET_NR_swapon:
-        p = lock_user_string(arg1);
+        if (!(p = lock_user_string(arg1)))
+            goto efault;
         ret = get_errno(swapon(p, arg2));
         unlock_user(p, arg1, 0);
         break;
@@ -3579,7 +3696,8 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
         {
             abi_ulong *v;
             abi_ulong v1, v2, v3, v4, v5, v6;
-            v = lock_user(arg1, 6 * sizeof(abi_ulong), 1);
+            if (!(v = lock_user(VERIFY_READ, arg1, 6 * sizeof(abi_ulong), 1)))
+                goto efault;
             v1 = tswapl(v[0]);
             v2 = tswapl(v[1]);
             v3 = tswapl(v[2]);
@@ -3650,7 +3768,8 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
         break;
 #endif
     case TARGET_NR_truncate:
-        p = lock_user_string(arg1);
+        if (!(p = lock_user_string(arg1)))
+            goto efault;
         ret = get_errno(truncate(p, arg2));
         unlock_user(p, arg1, 0);
         break;
@@ -3662,18 +3781,10 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
         break;
 #if defined(TARGET_NR_fchmodat) && defined(__NR_fchmodat)
     case TARGET_NR_fchmodat:
-        if (!arg2) {
-            ret = -TARGET_EFAULT;
-            goto fail;
-        }
-        p = lock_user_string(arg2);
-        if (!access_ok(VERIFY_READ, p, 1))
-            /* Don't "goto fail" so that cleanup can happen. */
-            ret = -TARGET_EFAULT;
-        else
-            ret = get_errno(sys_fchmodat(arg1, p, arg3, arg4));
-        if (p)
-            unlock_user(p, arg2, 0);
+        if (!(p = lock_user_string(arg2)))
+            goto efault;
+        ret = get_errno(sys_fchmodat(arg1, p, arg3, arg4));
+        unlock_user(p, arg2, 0);
         break;
 #endif
     case TARGET_NR_getpriority:
@@ -3690,25 +3801,26 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
         goto unimplemented;
 #endif
     case TARGET_NR_statfs:
-        p = lock_user_string(arg1);
+        if (!(p = lock_user_string(arg1)))
+            goto efault;
         ret = get_errno(statfs(path(p), &stfs));
         unlock_user(p, arg1, 0);
     convert_statfs:
         if (!is_error(ret)) {
             struct target_statfs *target_stfs;
 
-            lock_user_struct(target_stfs, arg2, 0);
-            /* ??? put_user is probably wrong.  */
-            put_user(stfs.f_type, &target_stfs->f_type);
-            put_user(stfs.f_bsize, &target_stfs->f_bsize);
-            put_user(stfs.f_blocks, &target_stfs->f_blocks);
-            put_user(stfs.f_bfree, &target_stfs->f_bfree);
-            put_user(stfs.f_bavail, &target_stfs->f_bavail);
-            put_user(stfs.f_files, &target_stfs->f_files);
-            put_user(stfs.f_ffree, &target_stfs->f_ffree);
-            put_user(stfs.f_fsid.__val[0], &target_stfs->f_fsid.val[0]);
-            put_user(stfs.f_fsid.__val[1], &target_stfs->f_fsid.val[1]);
-            put_user(stfs.f_namelen, &target_stfs->f_namelen);
+            if (!lock_user_struct(VERIFY_WRITE, target_stfs, arg2, 0))
+                goto efault;
+            __put_user(stfs.f_type, &target_stfs->f_type);
+            __put_user(stfs.f_bsize, &target_stfs->f_bsize);
+            __put_user(stfs.f_blocks, &target_stfs->f_blocks);
+            __put_user(stfs.f_bfree, &target_stfs->f_bfree);
+            __put_user(stfs.f_bavail, &target_stfs->f_bavail);
+            __put_user(stfs.f_files, &target_stfs->f_files);
+            __put_user(stfs.f_ffree, &target_stfs->f_ffree);
+            __put_user(stfs.f_fsid.__val[0], &target_stfs->f_fsid.val[0]);
+            __put_user(stfs.f_fsid.__val[1], &target_stfs->f_fsid.val[1]);
+            __put_user(stfs.f_namelen, &target_stfs->f_namelen);
             unlock_user_struct(target_stfs, arg2, 1);
         }
         break;
@@ -3717,26 +3829,27 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
         goto convert_statfs;
 #ifdef TARGET_NR_statfs64
     case TARGET_NR_statfs64:
-        p = lock_user_string(arg1);
+        if (!(p = lock_user_string(arg1)))
+            goto efault;
         ret = get_errno(statfs(path(p), &stfs));
         unlock_user(p, arg1, 0);
     convert_statfs64:
         if (!is_error(ret)) {
             struct target_statfs64 *target_stfs;
 
-            lock_user_struct(target_stfs, arg3, 0);
-            /* ??? put_user is probably wrong.  */
-            put_user(stfs.f_type, &target_stfs->f_type);
-            put_user(stfs.f_bsize, &target_stfs->f_bsize);
-            put_user(stfs.f_blocks, &target_stfs->f_blocks);
-            put_user(stfs.f_bfree, &target_stfs->f_bfree);
-            put_user(stfs.f_bavail, &target_stfs->f_bavail);
-            put_user(stfs.f_files, &target_stfs->f_files);
-            put_user(stfs.f_ffree, &target_stfs->f_ffree);
-            put_user(stfs.f_fsid.__val[0], &target_stfs->f_fsid.val[0]);
-            put_user(stfs.f_fsid.__val[1], &target_stfs->f_fsid.val[1]);
-            put_user(stfs.f_namelen, &target_stfs->f_namelen);
-            unlock_user_struct(target_stfs, arg3, 0);
+            if (!lock_user_struct(VERIFY_WRITE, target_stfs, arg3, 0))
+                goto efault;
+            __put_user(stfs.f_type, &target_stfs->f_type);
+            __put_user(stfs.f_bsize, &target_stfs->f_bsize);
+            __put_user(stfs.f_blocks, &target_stfs->f_blocks);
+            __put_user(stfs.f_bfree, &target_stfs->f_bfree);
+            __put_user(stfs.f_bavail, &target_stfs->f_bavail);
+            __put_user(stfs.f_files, &target_stfs->f_files);
+            __put_user(stfs.f_ffree, &target_stfs->f_ffree);
+            __put_user(stfs.f_fsid.__val[0], &target_stfs->f_fsid.val[0]);
+            __put_user(stfs.f_fsid.__val[1], &target_stfs->f_fsid.val[1]);
+            __put_user(stfs.f_namelen, &target_stfs->f_namelen);
+            unlock_user_struct(target_stfs, arg3, 1);
         }
         break;
     case TARGET_NR_fstatfs64:
@@ -3839,7 +3952,8 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
 #endif
 
     case TARGET_NR_syslog:
-        p = lock_user_string(arg2);
+        if (!(p = lock_user_string(arg2)))
+            goto efault;
         ret = get_errno(sys_syslog((int)arg1, p, (int)arg3));
         unlock_user(p, arg2, 0);
         break;
@@ -3880,12 +3994,14 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
         }
         break;
     case TARGET_NR_stat:
-        p = lock_user_string(arg1);
+        if (!(p = lock_user_string(arg1)))
+            goto efault;
         ret = get_errno(stat(path(p), &st));
         unlock_user(p, arg1, 0);
         goto do_stat;
     case TARGET_NR_lstat:
-        p = lock_user_string(arg1);
+        if (!(p = lock_user_string(arg1)))
+            goto efault;
         ret = get_errno(lstat(path(p), &st));
         unlock_user(p, arg1, 0);
         goto do_stat;
@@ -3896,7 +4012,8 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
             if (!is_error(ret)) {
                 struct target_stat *target_st;
 
-                lock_user_struct(target_st, arg2, 0);
+                if (!lock_user_struct(VERIFY_WRITE, target_st, arg2, 0))
+                    goto efault;
 #if defined(TARGET_MIPS) || (defined(TARGET_SPARC64) && !defined(TARGET_ABI32))
                 target_st->st_dev = tswap32(st.st_dev);
 #else
@@ -3979,7 +4096,8 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
         break;
 #ifdef TARGET_NR_swapoff
     case TARGET_NR_swapoff:
-        p = lock_user_string(arg1);
+        if (!(p = lock_user_string(arg1)))
+            goto efault;
         ret = get_errno(swapoff(p));
         unlock_user(p, arg1, 0);
         break;
@@ -3991,8 +4109,8 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
             ret = get_errno(sysinfo(&value));
             if (!is_error(ret) && arg1)
             {
-                /* ??? __put_user is probably wrong.  */
-                lock_user_struct(target_value, arg1, 0);
+                if (!lock_user_struct(VERIFY_WRITE, target_value, arg1, 0))
+                    goto efault;
                 __put_user(value.uptime, &target_value->uptime);
                 __put_user(value.loads[0], &target_value->loads[0]);
                 __put_user(value.loads[1], &target_value->loads[1]);
@@ -4030,7 +4148,8 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
         break;
 #endif
     case TARGET_NR_setdomainname:
-        p = lock_user_string(arg1);
+        if (!(p = lock_user_string(arg1)))
+            goto efault;
         ret = get_errno(setdomainname(p, arg2));
         unlock_user(p, arg1, 0);
         break;
@@ -4039,7 +4158,8 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
         {
             struct new_utsname * buf;
 
-            lock_user_struct(buf, arg1, 0);
+            if (!lock_user_struct(VERIFY_WRITE, buf, arg1, 0))
+                goto efault;
             ret = get_errno(sys_uname(buf));
             if (!is_error(ret)) {
                 /* Overrite the native machine name with whatever is being
@@ -4124,7 +4244,7 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
 
 	    dirp = malloc(count);
 	    if (!dirp) {
-                ret = -TARGET_EFAULT;
+                ret = -TARGET_ENOMEM;
                 goto fail;
             }
 
@@ -4138,7 +4258,8 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
 
 		count1 = 0;
                 de = dirp;
-                target_dirp = lock_user(arg2, count, 0);
+                if (!(target_dirp = lock_user(VERIFY_WRITE, arg2, count, 0)))
+                    goto efault;
 		tde = target_dirp;
                 while (len > 0) {
                     reclen = de->d_reclen;
@@ -4157,8 +4278,8 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
 		    count1 += treclen;
                 }
 		ret = count1;
+                unlock_user(target_dirp, arg2, ret);
             }
-            unlock_user(target_dirp, arg2, ret);
 	    free(dirp);
         }
 #else
@@ -4166,7 +4287,8 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
             struct dirent *dirp;
             abi_long count = arg3;
 
-            dirp = lock_user(arg2, count, 0);
+            if (!(dirp = lock_user(VERIFY_WRITE, arg2, count, 0)))
+                goto efault;
             ret = get_errno(sys_getdents(arg1, dirp, count));
             if (!is_error(ret)) {
                 struct dirent *de;
@@ -4193,7 +4315,8 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
         {
             struct dirent64 *dirp;
             abi_long count = arg3;
-            dirp = lock_user(arg2, count, 0);
+            if (!(dirp = lock_user(VERIFY_WRITE, arg2, count, 0)))
+                goto efault;
             ret = get_errno(sys_getdents64(arg1, dirp, count));
             if (!is_error(ret)) {
                 struct dirent64 *de;
@@ -4229,7 +4352,9 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
             struct pollfd *pfd;
             unsigned int i;
 
-            target_pfd = lock_user(arg1, sizeof(struct target_pollfd) * nfds, 1);
+            target_pfd = lock_user(VERIFY_WRITE, arg1, sizeof(struct target_pollfd) * nfds, 1);
+            if (!target_pfd)
+                goto efault;
             pfd = alloca(sizeof(struct pollfd) * nfds);
             for(i = 0; i < nfds; i++) {
                 pfd[i].fd = tswap32(target_pfd[i].fd);
@@ -4258,7 +4383,7 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
             struct iovec *vec;
 
             vec = alloca(count * sizeof(struct iovec));
-            lock_iovec(vec, arg2, count, 0);
+            lock_iovec(VERIFY_WRITE, vec, arg2, count, 0);
             ret = get_errno(readv(arg1, vec, count));
             unlock_iovec(vec, arg2, count, 1);
         }
@@ -4269,7 +4394,7 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
             struct iovec *vec;
 
             vec = alloca(count * sizeof(struct iovec));
-            lock_iovec(vec, arg2, count, 1);
+            lock_iovec(VERIFY_READ, vec, arg2, count, 1);
             ret = get_errno(writev(arg1, vec, count));
             unlock_iovec(vec, arg2, count, 0);
         }
@@ -4292,7 +4417,8 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
             struct sched_param *target_schp;
             struct sched_param schp;
 
-            lock_user_struct(target_schp, arg2, 1);
+            if (!lock_user_struct(VERIFY_READ, target_schp, arg2, 1))
+                goto efault;
             schp.sched_priority = tswap32(target_schp->sched_priority);
             unlock_user_struct(target_schp, arg2, 0);
             ret = get_errno(sched_setparam(arg1, &schp));
@@ -4304,7 +4430,8 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
             struct sched_param schp;
             ret = get_errno(sched_getparam(arg1, &schp));
             if (!is_error(ret)) {
-                lock_user_struct(target_schp, arg2, 0);
+                if (!lock_user_struct(VERIFY_WRITE, target_schp, arg2, 0))
+                    goto efault;
                 target_schp->sched_priority = tswap32(schp.sched_priority);
                 unlock_user_struct(target_schp, arg2, 1);
             }
@@ -4314,7 +4441,8 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
         {
             struct sched_param *target_schp;
             struct sched_param schp;
-            lock_user_struct(target_schp, arg3, 1);
+            if (!lock_user_struct(VERIFY_READ, target_schp, arg3, 1))
+                goto efault;
             schp.sched_priority = tswap32(target_schp->sched_priority);
             unlock_user_struct(target_schp, arg3, 0);
             ret = get_errno(sched_setscheduler(arg1, arg2, &schp));
@@ -4378,18 +4506,21 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
 #ifdef TARGET_NR_pread
     case TARGET_NR_pread:
         page_unprotect_range(arg2, arg3);
-        p = lock_user(arg2, arg3, 0);
+        if (!(p = lock_user(VERIFY_WRITE, arg2, arg3, 0)))
+            goto efault;
         ret = get_errno(pread(arg1, p, arg3, arg4));
         unlock_user(p, arg2, ret);
         break;
     case TARGET_NR_pwrite:
-        p = lock_user(arg2, arg3, 1);
+        if (!(p = lock_user(VERIFY_READ, arg2, arg3, 1)))
+            goto efault;
         ret = get_errno(pwrite(arg1, p, arg3, arg4));
         unlock_user(p, arg2, 0);
         break;
 #endif
     case TARGET_NR_getcwd:
-        p = lock_user(arg1, arg2, 0);
+        if (!(p = lock_user(VERIFY_WRITE, arg1, arg2, 0)))
+            goto efault;
         ret = get_errno(sys_getcwd1(p, arg2));
         unlock_user(p, arg1, ret);
         break;
@@ -4400,9 +4531,7 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
     case TARGET_NR_sigaltstack:
 #if defined(TARGET_I386) || defined(TARGET_ARM) || defined(TARGET_MIPS) || \
     defined(TARGET_SPARC) || defined(TARGET_PPC) || defined(TARGET_ALPHA)
-        ret = do_sigaltstack((struct target_sigaltstack *)arg1,
-                             (struct target_sigaltstack *)arg2,
-                             get_sp_from_cpustate((CPUState *)cpu_env));
+        ret = do_sigaltstack(arg1, arg2, get_sp_from_cpustate((CPUState *)cpu_env));
         break;
 #else
         goto unimplemented;
@@ -4429,7 +4558,8 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
 	ret = get_errno(getrlimit(arg1, &rlim));
 	if (!is_error(ret)) {
 	    struct target_rlimit *target_rlim;
-            lock_user_struct(target_rlim, arg2, 0);
+            if (!lock_user_struct(VERIFY_WRITE, target_rlim, arg2, 0))
+                goto efault;
 	    target_rlim->rlim_cur = tswapl(rlim.rlim_cur);
 	    target_rlim->rlim_max = tswapl(rlim.rlim_max);
             unlock_user_struct(target_rlim, arg2, 1);
@@ -4439,7 +4569,8 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
 #endif
 #ifdef TARGET_NR_truncate64
     case TARGET_NR_truncate64:
-        p = lock_user_string(arg1);
+        if (!(p = lock_user_string(arg1)))
+            goto efault;
 	ret = target_truncate64(cpu_env, p, arg2, arg3, arg4);
         unlock_user(p, arg1, 0);
 	break;
@@ -4451,14 +4582,16 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
 #endif
 #ifdef TARGET_NR_stat64
     case TARGET_NR_stat64:
-        p = lock_user_string(arg1);
+        if (!(p = lock_user_string(arg1)))
+            goto efault;
         ret = get_errno(stat(path(p), &st));
         unlock_user(p, arg1, 0);
         goto do_stat64;
 #endif
 #ifdef TARGET_NR_lstat64
     case TARGET_NR_lstat64:
-        p = lock_user_string(arg1);
+        if (!(p = lock_user_string(arg1)))
+            goto efault;
         ret = get_errno(lstat(path(p), &st));
         unlock_user(p, arg1, 0);
         goto do_stat64;
@@ -4472,52 +4605,53 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
 #ifdef TARGET_ARM
                 if (((CPUARMState *)cpu_env)->eabi) {
                     struct target_eabi_stat64 *target_st;
-                    lock_user_struct(target_st, arg2, 1);
+
+                    if (!lock_user_struct(VERIFY_WRITE, target_st, arg2, 0))
+                        goto efault;
                     memset(target_st, 0, sizeof(struct target_eabi_stat64));
-                    /* put_user is probably wrong.  */
-                    put_user(st.st_dev, &target_st->st_dev);
-                    put_user(st.st_ino, &target_st->st_ino);
+                    __put_user(st.st_dev, &target_st->st_dev);
+                    __put_user(st.st_ino, &target_st->st_ino);
 #ifdef TARGET_STAT64_HAS_BROKEN_ST_INO
-                    put_user(st.st_ino, &target_st->__st_ino);
-#endif
-                    put_user(st.st_mode, &target_st->st_mode);
-                    put_user(st.st_nlink, &target_st->st_nlink);
-                    put_user(st.st_uid, &target_st->st_uid);
-                    put_user(st.st_gid, &target_st->st_gid);
-                    put_user(st.st_rdev, &target_st->st_rdev);
-                    /* XXX: better use of kernel struct */
-                    put_user(st.st_size, &target_st->st_size);
-                    put_user(st.st_blksize, &target_st->st_blksize);
-                    put_user(st.st_blocks, &target_st->st_blocks);
-                    put_user(st.st_atime, &target_st->target_st_atime);
-                    put_user(st.st_mtime, &target_st->target_st_mtime);
-                    put_user(st.st_ctime, &target_st->target_st_ctime);
-                    unlock_user_struct(target_st, arg2, 0);
+                    __put_user(st.st_ino, &target_st->__st_ino);
+#endif
+                    __put_user(st.st_mode, &target_st->st_mode);
+                    __put_user(st.st_nlink, &target_st->st_nlink);
+                    __put_user(st.st_uid, &target_st->st_uid);
+                    __put_user(st.st_gid, &target_st->st_gid);
+                    __put_user(st.st_rdev, &target_st->st_rdev);
+                    __put_user(st.st_size, &target_st->st_size);
+                    __put_user(st.st_blksize, &target_st->st_blksize);
+                    __put_user(st.st_blocks, &target_st->st_blocks);
+                    __put_user(st.st_atime, &target_st->target_st_atime);
+                    __put_user(st.st_mtime, &target_st->target_st_mtime);
+                    __put_user(st.st_ctime, &target_st->target_st_ctime);
+                    unlock_user_struct(target_st, arg2, 1);
                 } else
 #endif
                 {
                     struct target_stat64 *target_st;
-                    lock_user_struct(target_st, arg2, 1);
+
+                    if (!lock_user_struct(VERIFY_WRITE, target_st, arg2, 0))
+                        goto efault;
                     memset(target_st, 0, sizeof(struct target_stat64));
-                    /* ??? put_user is probably wrong.  */
-                    put_user(st.st_dev, &target_st->st_dev);
-                    put_user(st.st_ino, &target_st->st_ino);
+                    __put_user(st.st_dev, &target_st->st_dev);
+                    __put_user(st.st_ino, &target_st->st_ino);
 #ifdef TARGET_STAT64_HAS_BROKEN_ST_INO
-                    put_user(st.st_ino, &target_st->__st_ino);
+                    __put_user(st.st_ino, &target_st->__st_ino);
 #endif
-                    put_user(st.st_mode, &target_st->st_mode);
-                    put_user(st.st_nlink, &target_st->st_nlink);
-                    put_user(st.st_uid, &target_st->st_uid);
-                    put_user(st.st_gid, &target_st->st_gid);
-                    put_user(st.st_rdev, &target_st->st_rdev);
+                    __put_user(st.st_mode, &target_st->st_mode);
+                    __put_user(st.st_nlink, &target_st->st_nlink);
+                    __put_user(st.st_uid, &target_st->st_uid);
+                    __put_user(st.st_gid, &target_st->st_gid);
+                    __put_user(st.st_rdev, &target_st->st_rdev);
                     /* XXX: better use of kernel struct */
-                    put_user(st.st_size, &target_st->st_size);
-                    put_user(st.st_blksize, &target_st->st_blksize);
-                    put_user(st.st_blocks, &target_st->st_blocks);
-                    put_user(st.st_atime, &target_st->target_st_atime);
-                    put_user(st.st_mtime, &target_st->target_st_mtime);
-                    put_user(st.st_ctime, &target_st->target_st_ctime);
-                    unlock_user_struct(target_st, arg2, 0);
+                    __put_user(st.st_size, &target_st->st_size);
+                    __put_user(st.st_blksize, &target_st->st_blksize);
+                    __put_user(st.st_blocks, &target_st->st_blocks);
+                    __put_user(st.st_atime, &target_st->target_st_atime);
+                    __put_user(st.st_mtime, &target_st->target_st_mtime);
+                    __put_user(st.st_ctime, &target_st->target_st_ctime);
+                    unlock_user_struct(target_st, arg2, 1);
                 }
             }
         }
@@ -4525,7 +4659,8 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
 #endif
 #ifdef USE_UID16
     case TARGET_NR_lchown:
-        p = lock_user_string(arg1);
+        if (!(p = lock_user_string(arg1)))
+            goto efault;
         ret = get_errno(lchown(p, low2highuid(arg2), low2highgid(arg3)));
         unlock_user(p, arg1, 0);
         break;
@@ -4557,7 +4692,9 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
             grouplist = alloca(gidsetsize * sizeof(gid_t));
             ret = get_errno(getgroups(gidsetsize, grouplist));
             if (!is_error(ret)) {
-                target_grouplist = lock_user(arg2, gidsetsize * 2, 0);
+                target_grouplist = lock_user(VERIFY_WRITE, arg2, gidsetsize * 2, 0);
+                if (!target_grouplist)
+                    goto efault;
                 for(i = 0;i < gidsetsize; i++)
                     target_grouplist[i] = tswap16(grouplist[i]);
                 unlock_user(target_grouplist, arg2, gidsetsize * 2);
@@ -4572,7 +4709,11 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
             int i;
 
             grouplist = alloca(gidsetsize * sizeof(gid_t));
-            target_grouplist = lock_user(arg2, gidsetsize * 2, 1);
+            target_grouplist = lock_user(VERIFY_READ, arg2, gidsetsize * 2, 1);
+            if (!target_grouplist) {
+                ret = -TARGET_EFAULT;
+                goto fail;
+            }
             for(i = 0;i < gidsetsize; i++)
                 grouplist[i] = tswap16(target_grouplist[i]);
             unlock_user(target_grouplist, arg2, 0);
@@ -4584,18 +4725,10 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
         break;
 #if defined(TARGET_NR_fchownat) && defined(__NR_fchownat)
     case TARGET_NR_fchownat:
-        if (!arg2) {
-            ret = -TARGET_EFAULT;
-            goto fail;
-        }
-        p = lock_user_string(arg2);
-        if (!access_ok(VERIFY_READ, p, 1))
-            /* Don't "goto fail" so that cleanup can happen. */
-            ret = -TARGET_EFAULT;
-	else
-            ret = get_errno(sys_fchownat(arg1, p, low2highuid(arg3), low2highgid(arg4), arg5));
-        if (p)
-            unlock_user(p, arg2, 0);
+        if (!(p = lock_user_string(arg2))) 
+            goto efault;
+        ret = get_errno(sys_fchownat(arg1, p, low2highuid(arg3), low2highgid(arg4), arg5));
+        unlock_user(p, arg2, 0);
         break;
 #endif
 #ifdef TARGET_NR_setresuid
@@ -4639,7 +4772,8 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
         break;
 #endif
     case TARGET_NR_chown:
-        p = lock_user_string(arg1);
+        if (!(p = lock_user_string(arg1)))
+            goto efault;
         ret = get_errno(chown(p, low2highuid(arg2), low2highgid(arg3)));
         unlock_user(p, arg1, 0);
         break;
@@ -4659,7 +4793,8 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
 
 #ifdef TARGET_NR_lchown32
     case TARGET_NR_lchown32:
-        p = lock_user_string(arg1);
+        if (!(p = lock_user_string(arg1)))
+            goto efault;
         ret = get_errno(lchown(p, arg2, arg3));
         unlock_user(p, arg1, 0);
         break;
@@ -4705,7 +4840,11 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
             grouplist = alloca(gidsetsize * sizeof(gid_t));
             ret = get_errno(getgroups(gidsetsize, grouplist));
             if (!is_error(ret)) {
-                target_grouplist = lock_user(arg2, gidsetsize * 4, 0);
+                target_grouplist = lock_user(VERIFY_WRITE, arg2, gidsetsize * 4, 0);
+                if (!target_grouplist) {
+                    ret = -TARGET_EFAULT;
+                    goto fail;
+                }
                 for(i = 0;i < gidsetsize; i++)
                     target_grouplist[i] = tswap32(grouplist[i]);
                 unlock_user(target_grouplist, arg2, gidsetsize * 4);
@@ -4722,7 +4861,11 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
             int i;
 
             grouplist = alloca(gidsetsize * sizeof(gid_t));
-            target_grouplist = lock_user(arg2, gidsetsize * 4, 1);
+            target_grouplist = lock_user(VERIFY_READ, arg2, gidsetsize * 4, 1);
+            if (!target_grouplist) {
+                ret = -TARGET_EFAULT;
+                goto fail;
+            }
             for(i = 0;i < gidsetsize; i++)
                 grouplist[i] = tswap32(target_grouplist[i]);
             unlock_user(target_grouplist, arg2, 0);
@@ -4773,7 +4916,8 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
 #endif
 #ifdef TARGET_NR_chown32
     case TARGET_NR_chown32:
-        p = lock_user_string(arg1);
+        if (!(p = lock_user_string(arg1)))
+            goto efault;
         ret = get_errno(chown(p, arg2, arg3));
         unlock_user(p, arg1, 0);
         break;
@@ -4843,7 +4987,10 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
         case TARGET_F_GETLK64:
 #ifdef TARGET_ARM
             if (((CPUARMState *)cpu_env)->eabi) {
-                lock_user_struct(target_efl, arg3, 1);
+                if (!lock_user_struct(VERIFY_READ, target_efl, arg3, 1)) {
+                    ret = -TARGET_EFAULT;
+                    goto fail;
+                }
                 fl.l_type = tswap16(target_efl->l_type);
                 fl.l_whence = tswap16(target_efl->l_whence);
                 fl.l_start = tswap64(target_efl->l_start);
@@ -4853,7 +5000,10 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
             } else
 #endif
             {
-                lock_user_struct(target_fl, arg3, 1);
+                if (!lock_user_struct(VERIFY_READ, target_fl, arg3, 1)) {
+                    ret = -TARGET_EFAULT;
+                    goto fail;
+                }
                 fl.l_type = tswap16(target_fl->l_type);
                 fl.l_whence = tswap16(target_fl->l_whence);
                 fl.l_start = tswap64(target_fl->l_start);
@@ -4865,7 +5015,10 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
 	    if (ret == 0) {
 #ifdef TARGET_ARM
                 if (((CPUARMState *)cpu_env)->eabi) {
-                    lock_user_struct(target_efl, arg3, 0);
+                    if (!lock_user_struct(VERIFY_WRITE, target_efl, arg3, 0)) {
+                        ret = -TARGET_EFAULT;
+                        goto fail;
+                    }
                     target_efl->l_type = tswap16(fl.l_type);
                     target_efl->l_whence = tswap16(fl.l_whence);
                     target_efl->l_start = tswap64(fl.l_start);
@@ -4875,7 +5028,10 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
                 } else
 #endif
                 {
-                    lock_user_struct(target_fl, arg3, 0);
+                    if (!lock_user_struct(VERIFY_WRITE, target_fl, arg3, 0)) {
+                        ret = -TARGET_EFAULT;
+                        goto fail;
+                    }
                     target_fl->l_type = tswap16(fl.l_type);
                     target_fl->l_whence = tswap16(fl.l_whence);
                     target_fl->l_start = tswap64(fl.l_start);
@@ -4890,7 +5046,10 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
         case TARGET_F_SETLKW64:
 #ifdef TARGET_ARM
             if (((CPUARMState *)cpu_env)->eabi) {
-                lock_user_struct(target_efl, arg3, 1);
+                if (!lock_user_struct(VERIFY_READ, target_efl, arg3, 1)) {
+                    ret = -TARGET_EFAULT;
+                    goto fail;
+                }
                 fl.l_type = tswap16(target_efl->l_type);
                 fl.l_whence = tswap16(target_efl->l_whence);
                 fl.l_start = tswap64(target_efl->l_start);
@@ -4900,7 +5059,10 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
             } else
 #endif
             {
-                lock_user_struct(target_fl, arg3, 1);
+                if (!lock_user_struct(VERIFY_READ, target_fl, arg3, 1)) {
+                    ret = -TARGET_EFAULT;
+                    goto fail;
+                }
                 fl.l_type = tswap16(target_fl->l_type);
                 fl.l_whence = tswap16(target_fl->l_whence);
                 fl.l_start = tswap64(target_fl->l_start);
@@ -4998,8 +5160,8 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
 
 #if defined(TARGET_NR_set_tid_address) && defined(__NR_set_tid_address)
     case TARGET_NR_set_tid_address:
-      ret = get_errno(set_tid_address((int *) arg1));
-      break;
+        ret = get_errno(set_tid_address((int *)g2h(arg1)));
+        break;
 #endif
 
 #if defined(TARGET_NR_tkill) && defined(__NR_tkill)
@@ -5028,14 +5190,12 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
             if (!arg2)
                 ret = get_errno(sys_utimensat(arg1, NULL, ts, arg4));
             else {
-                p = lock_user_string(arg2);
-                if (!access_ok(VERIFY_READ, p, 1))
-                    /* Don't "goto fail" so that cleanup can happen. */
+                if (!(p = lock_user_string(arg2))) {
                     ret = -TARGET_EFAULT;
-                else
-                    ret = get_errno(sys_utimensat(arg1, path(p), ts, arg4));
-                if (p)
-                    unlock_user(p, arg2, 0);
+                    goto fail;
+                }
+                ret = get_errno(sys_utimensat(arg1, path(p), ts, arg4));
+                unlock_user(p, arg2, 0);
             }
         }
 	break;
@@ -5050,11 +5210,14 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
         ret = -TARGET_ENOSYS;
         break;
     }
- fail:
+fail:
 #ifdef DEBUG
     gemu_log(" = %ld\n", ret);
 #endif
     if(do_strace)
         print_syscall_ret(num, ret);
     return ret;
+efault:
+    ret = -TARGET_EFAULT;
+    goto fail;
 }
