Skip to content

Commit

Permalink
linux-user: Fix error handling in lock_iovec()
Browse files Browse the repository at this point in the history
In lock_iovec() if lock_user() failed we were doing an unlock_user
but not a free(vec), which is the wrong way round. We were also
assuming that free() and unlock_user() don't touch errno, which
is not guaranteed. Fix both these problems.

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Signed-off-by: Riku Voipio <riku.voipio@linaro.org>
  • Loading branch information
pm215 authored and Riku Voipio committed Feb 18, 2014
1 parent 3a5d30b commit 501bb4b
Showing 1 changed file with 7 additions and 5 deletions.
12 changes: 7 additions & 5 deletions linux-user/syscall.c
Expand Up @@ -1707,6 +1707,7 @@ static struct iovec *lock_iovec(int type, abi_ulong target_addr,
struct iovec *vec;
abi_ulong total_len, max_len;
int i;
int err = 0;

if (count == 0) {
errno = 0;
Expand All @@ -1726,7 +1727,7 @@ static struct iovec *lock_iovec(int type, abi_ulong target_addr,
target_vec = lock_user(VERIFY_READ, target_addr,
count * sizeof(struct target_iovec), 1);
if (target_vec == NULL) {
errno = EFAULT;
err = EFAULT;
goto fail2;
}

Expand All @@ -1740,15 +1741,15 @@ static struct iovec *lock_iovec(int type, abi_ulong target_addr,
abi_long len = tswapal(target_vec[i].iov_len);

if (len < 0) {
errno = EINVAL;
err = EINVAL;
goto fail;
} else if (len == 0) {
/* Zero length pointer is ignored. */
vec[i].iov_base = 0;
} else {
vec[i].iov_base = lock_user(type, base, len, copy);
if (!vec[i].iov_base) {
errno = EFAULT;
err = EFAULT;
goto fail;
}
if (len > max_len - total_len) {
Expand All @@ -1763,9 +1764,10 @@ static struct iovec *lock_iovec(int type, abi_ulong target_addr,
return vec;

fail:
free(vec);
fail2:
unlock_user(target_vec, target_addr, 0);
fail2:
free(vec);
errno = err;
return NULL;
}

Expand Down

0 comments on commit 501bb4b

Please sign in to comment.