diff mbox

[12/12] linux-user: writev Partial Writes

Message ID 1407170739-12237-13-git-send-email-tommusta@gmail.com
State New
Headers show

Commit Message

Tom Musta Aug. 4, 2014, 4:45 p.m. UTC
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 <tommusta@gmail.com>

Comments

Peter Maydell Aug. 4, 2014, 5:29 p.m. UTC | #1
On 4 August 2014 17:45, Tom Musta <tommusta@gmail.com> wrote:
> 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 <tommusta@gmail.com>
>
> 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;

I would use a bool here rather than int. Other than that nit,


Reviewed-by: Peter Maydell <peter.maydell@linaro.org>

thanks
-- PMM
diff mbox

Patch

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;