[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Qemu-devel] [PATCH 2/3] block: Fix NULL deference for unaligned write i
From: |
Fam Zheng |
Subject: |
[Qemu-devel] [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