Commit d732dcb442ce810709f48d7a105b573efda118a2

Authored by balrog
1 parent a2f86d8e

Fix iovec for the case with invalid elements (Lauro Ramos Venancio).

We must call the writev even if an iovec element is invalid. For
example, if the second element is invalid, the linux process the first
one.


git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@5562 c046a42c-6fe2-441c-8c8c-71466251a162
Showing 1 changed file with 7 additions and 13 deletions
linux-user/syscall.c
... ... @@ -1064,7 +1064,7 @@ static abi_long lock_iovec(int type, struct iovec *vec, abi_ulong target_addr,
1064 1064 {
1065 1065 struct target_iovec *target_vec;
1066 1066 abi_ulong base;
1067   - int i, j;
  1067 + int i;
1068 1068  
1069 1069 target_vec = lock_user(VERIFY_READ, target_addr, count * sizeof(struct target_iovec), 1);
1070 1070 if (!target_vec)
... ... @@ -1074,8 +1074,8 @@ static abi_long lock_iovec(int type, struct iovec *vec, abi_ulong target_addr,
1074 1074 vec[i].iov_len = tswapl(target_vec[i].iov_len);
1075 1075 if (vec[i].iov_len != 0) {
1076 1076 vec[i].iov_base = lock_user(type, base, vec[i].iov_len, copy);
1077   - if (!vec[i].iov_base && vec[i].iov_len)
1078   - goto fail;
  1077 + /* Don't check lock_user return value. We must call writev even
  1078 + if a element has invalid base address. */
1079 1079 } else {
1080 1080 /* zero length pointer is ignored */
1081 1081 vec[i].iov_base = NULL;
... ... @@ -1083,14 +1083,6 @@ static abi_long lock_iovec(int type, struct iovec *vec, abi_ulong target_addr,
1083 1083 }
1084 1084 unlock_user (target_vec, target_addr, 0);
1085 1085 return 0;
1086   - fail:
1087   - /* failure - unwind locks */
1088   - for (j = 0; j < i; j++) {
1089   - base = tswapl(target_vec[j].iov_base);
1090   - unlock_user(vec[j].iov_base, base, 0);
1091   - }
1092   - unlock_user (target_vec, target_addr, 0);
1093   - return -TARGET_EFAULT;
1094 1086 }
1095 1087  
1096 1088 static abi_long unlock_iovec(struct iovec *vec, abi_ulong target_addr,
... ... @@ -1104,8 +1096,10 @@ static abi_long unlock_iovec(struct iovec *vec, abi_ulong target_addr,
1104 1096 if (!target_vec)
1105 1097 return -TARGET_EFAULT;
1106 1098 for(i = 0;i < count; i++) {
1107   - base = tswapl(target_vec[i].iov_base);
1108   - unlock_user(vec[i].iov_base, base, copy ? vec[i].iov_len : 0);
  1099 + if (target_vec[i].iov_base) {
  1100 + base = tswapl(target_vec[i].iov_base);
  1101 + unlock_user(vec[i].iov_base, base, copy ? vec[i].iov_len : 0);
  1102 + }
1109 1103 }
1110 1104 unlock_user (target_vec, target_addr, 0);
1111 1105  
... ...