Index: qemu-arm-eabi/linux-user/syscall.c =================================================================== --- qemu-arm-eabi.orig/linux-user/syscall.c 2008-10-09 15:51:24.000000000 -0300 +++ qemu-arm-eabi/linux-user/syscall.c 2008-10-09 16:02:15.000000000 -0300 @@ -1165,7 +1165,7 @@ { struct target_iovec *target_vec; abi_ulong base; - int i, j; + int i; target_vec = lock_user(VERIFY_READ, target_addr, count * sizeof(struct target_iovec), 1); if (!target_vec) @@ -1175,8 +1175,8 @@ vec[i].iov_len = tswapl(target_vec[i].iov_len); if (vec[i].iov_len != 0) { vec[i].iov_base = lock_user(type, base, vec[i].iov_len, copy); - if (!vec[i].iov_base && vec[i].iov_len) - goto fail; + /* Don't check lock_user return value. We must call writev even + if a element has invalid base address. */ } else { /* zero length pointer is ignored */ vec[i].iov_base = NULL; @@ -1184,14 +1184,6 @@ } 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 abi_long unlock_iovec(struct iovec *vec, abi_ulong target_addr, @@ -1205,8 +1197,10 @@ 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); + if (target_vec[i].iov_base) { + 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);