qemu-stable
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Qemu-stable] [PATCH 2/3] block: Fix NULL deference for unaligned write


From: Fam Zheng
Subject: [Qemu-stable] [PATCH 2/3] block: Fix NULL deference for unaligned write if qiov is NULL
Date: Fri, 24 Apr 2015 16:33:55 +0800

For zero write, qiov passed by callers (qemu-io "write -z" and
scsi-disk "write same") is NULL.

Commit fc3959e466 fixed bdrv_co_write_zeroes which is the common case
for this bug, but it still exists in bdrv_aio_write_zeroes. A simpler
fix would be in bdrv_co_do_pwritev which is the NULL dereference point
and covers both cases.

So don't access it in bdrv_co_do_pwritev, use a zeroed buffer instead.
Device model who calls into block layer should check the request size.

Signed-off-by: Fam Zheng <address@hidden>
---
 block.c | 24 ++++++++++++++++++++----
 1 file changed, 20 insertions(+), 4 deletions(-)

diff --git a/block.c b/block.c
index f2f8ae7..878a72d 100644
--- a/block.c
+++ b/block.c
@@ -3386,6 +3386,7 @@ static int coroutine_fn 
bdrv_co_do_pwritev(BlockDriverState *bs,
     uint64_t align = bdrv_get_align(bs);
     uint8_t *head_buf = NULL;
     uint8_t *tail_buf = NULL;
+    uint8_t *qiov_buf = NULL;
     QEMUIOVector local_qiov;
     bool use_local_qiov = false;
     int ret;
@@ -3436,9 +3437,15 @@ static int coroutine_fn 
bdrv_co_do_pwritev(BlockDriverState *bs,
         }
         BLKDBG_EVENT(bs, BLKDBG_PWRITEV_RMW_AFTER_HEAD);
 
-        qemu_iovec_init(&local_qiov, qiov->niov + 2);
+        qemu_iovec_init(&local_qiov, qiov ? qiov->niov + 2 : 3);
         qemu_iovec_add(&local_qiov, head_buf, offset & (align - 1));
-        qemu_iovec_concat(&local_qiov, qiov, 0, qiov->size);
+        if (qiov) {
+            qemu_iovec_concat(&local_qiov, qiov, 0, qiov->size);
+        } else {
+            qiov_buf = qemu_blockalign(bs, bytes);
+            memset(qiov_buf, 0, bytes);
+            qemu_iovec_add(&local_qiov, qiov_buf, bytes);
+        }
         use_local_qiov = true;
 
         bytes += offset & (align - 1);
@@ -3471,8 +3478,16 @@ static int coroutine_fn 
bdrv_co_do_pwritev(BlockDriverState *bs,
         BLKDBG_EVENT(bs, BLKDBG_PWRITEV_RMW_AFTER_TAIL);
 
         if (!use_local_qiov) {
-            qemu_iovec_init(&local_qiov, qiov->niov + 1);
-            qemu_iovec_concat(&local_qiov, qiov, 0, qiov->size);
+            qemu_iovec_init(&local_qiov, qiov ? qiov->niov + 1 : 2);
+            if (qiov) {
+                qemu_iovec_concat(&local_qiov, qiov, 0, qiov->size);
+            } else {
+                if (!qiov_buf) {
+                    qiov_buf = qemu_blockalign(bs, bytes);
+                    memset(qiov_buf, 0, bytes);
+                }
+                qemu_iovec_add(&local_qiov, qiov_buf, bytes);
+            }
             use_local_qiov = true;
         }
 
@@ -3498,6 +3513,7 @@ fail:
     }
     qemu_vfree(head_buf);
     qemu_vfree(tail_buf);
+    qemu_vfree(qiov_buf);
 
     return ret;
 }
-- 
1.9.3




reply via email to

[Prev in Thread] Current Thread [Next in Thread]