From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from eggs.gnu.org ([2001:4830:134:3::10]:35501) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1XELQ4-0007Z5-MV for qemu-devel@nongnu.org; Mon, 04 Aug 2014 12:47:41 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1XELPv-0008CP-Jk for qemu-devel@nongnu.org; Mon, 04 Aug 2014 12:47:32 -0400 From: Tom Musta Date: Mon, 4 Aug 2014 11:45:39 -0500 Message-Id: <1407170739-12237-13-git-send-email-tommusta@gmail.com> In-Reply-To: <1407170739-12237-1-git-send-email-tommusta@gmail.com> References: <1407170739-12237-1-git-send-email-tommusta@gmail.com> Subject: [Qemu-devel] [PATCH 12/12] linux-user: writev Partial Writes List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , To: qemu-devel@nongnu.org, qemu-ppc@nongnu.org Cc: Tom Musta , riku.voipio@linaro.org, agraf@suse.de Although not technically not required by POSIX, the writev system call will typically write out its buffers individually. That is, if the first buffer is written successfully, but the second buffer pointer is invalid, then the first chuck will be written and its size is returned. Signed-off-by: Tom Musta diff --git a/linux-user/syscall.c b/linux-user/syscall.c index fea54be..19e78dc 100644 --- a/linux-user/syscall.c +++ b/linux-user/syscall.c @@ -1798,6 +1798,7 @@ static struct iovec *lock_iovec(int type, abi_ulong target_addr, abi_ulong total_len, max_len; int i; int err = 0; + int bad_address = 0; if (count == 0) { errno = 0; @@ -1838,9 +1839,20 @@ static struct iovec *lock_iovec(int type, abi_ulong target_addr, vec[i].iov_base = 0; } else { vec[i].iov_base = lock_user(type, base, len, copy); + /* If the first buffer pointer is bad, this is a fault. But + * subsequent bad buffers will result in a partial write; this + * is realized by filling the vector with null pointers and + * zero lengths. */ if (!vec[i].iov_base) { - err = EFAULT; - goto fail; + if (i == 0) { + err = EFAULT; + goto fail; + } else { + bad_address = 1; + } + } + if (bad_address) { + len = 0; } if (len > max_len - total_len) { len = max_len - total_len; -- 1.7.1