aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorbalrog <balrog@c046a42c-6fe2-441c-8c8c-71466251a162>2008-10-28 10:21:03 +0000
committerbalrog <balrog@c046a42c-6fe2-441c-8c8c-71466251a162>2008-10-28 10:21:03 +0000
commitd732dcb442ce810709f48d7a105b573efda118a2 (patch)
tree3f2625598c78ebac8bace395df92be6508942cb5
parenta2f86d8e08b530679bdcf8662c51e21c2e9ad46e (diff)
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
-rw-r--r--linux-user/syscall.c20
1 files changed, 7 insertions, 13 deletions
diff --git a/linux-user/syscall.c b/linux-user/syscall.c
index 91deb80ba6..06d1597650 100644
--- a/linux-user/syscall.c
+++ b/linux-user/syscall.c
@@ -1064,7 +1064,7 @@ static abi_long lock_iovec(int type, struct iovec *vec, abi_ulong target_addr,
{
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)
@@ -1074,8 +1074,8 @@ static abi_long lock_iovec(int type, struct iovec *vec, abi_ulong target_addr,
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;
@@ -1083,14 +1083,6 @@ static abi_long lock_iovec(int type, struct iovec *vec, abi_ulong target_addr,
}
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,
@@ -1104,8 +1096,10 @@ static abi_long unlock_iovec(struct iovec *vec, abi_ulong target_addr,
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);