|
|
958e1b |
From 7262d3c7280343601ab3b0be0d469ffb867b86d7 Mon Sep 17 00:00:00 2001
|
|
|
958e1b |
From: Markus Armbruster <armbru@redhat.com>
|
|
|
958e1b |
Date: Fri, 31 Oct 2014 16:29:55 +0100
|
|
|
958e1b |
Subject: [PATCH 18/19] ide: Treat read/write beyond end as invalid
|
|
|
958e1b |
|
|
|
958e1b |
Message-id: <1414772996-17272-5-git-send-email-armbru@redhat.com>
|
|
|
958e1b |
Patchwork-id: 62015
|
|
|
958e1b |
O-Subject: [PATCH RHEL-7.1 qemu-kvm 4/5] ide: Treat read/write beyond end as invalid
|
|
|
958e1b |
Bugzilla: 1085232
|
|
|
958e1b |
RH-Acked-by: Paolo Bonzini <pbonzini@redhat.com>
|
|
|
958e1b |
RH-Acked-by: Fam Zheng <famz@redhat.com>
|
|
|
958e1b |
|
|
|
958e1b |
The block layer fails such reads and writes just fine. However, they
|
|
|
958e1b |
then get treated like valid operations that fail: the error action
|
|
|
958e1b |
gets executed. Unwanted; reporting the error to the guest is the only
|
|
|
958e1b |
sensible action.
|
|
|
958e1b |
|
|
|
958e1b |
Reject them before passing them to the block layer. This bypasses the
|
|
|
958e1b |
error action and I/O accounting. Not quite correct for DMA, because
|
|
|
958e1b |
DMA can fail after some success, and when that happens, the part that
|
|
|
958e1b |
succeeded isn't counted. Tolerable, because I/O accounting is an
|
|
|
958e1b |
inconsistent mess anyway.
|
|
|
958e1b |
|
|
|
958e1b |
Signed-off-by: Markus Armbruster <armbru@redhat.com>
|
|
|
958e1b |
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
|
|
|
958e1b |
(cherry picked from commit 58ac321135af890b503ebe56d0d00e184779918f)
|
|
|
958e1b |
Signed-off-by: Miroslav Rezanina <mrezanin@redhat.com>
|
|
|
958e1b |
---
|
|
|
958e1b |
hw/ide/core.c | 28 ++++++++++++++++++++++++++++
|
|
|
958e1b |
1 file changed, 28 insertions(+)
|
|
|
958e1b |
|
|
|
958e1b |
diff --git a/hw/ide/core.c b/hw/ide/core.c
|
|
|
958e1b |
index 98128fb..4c36f52 100644
|
|
|
958e1b |
--- a/hw/ide/core.c
|
|
|
958e1b |
+++ b/hw/ide/core.c
|
|
|
958e1b |
@@ -513,6 +513,18 @@ static void ide_rw_error(IDEState *s) {
|
|
|
958e1b |
ide_set_irq(s->bus);
|
|
|
958e1b |
}
|
|
|
958e1b |
|
|
|
958e1b |
+static bool ide_sect_range_ok(IDEState *s,
|
|
|
958e1b |
+ uint64_t sector, uint64_t nb_sectors)
|
|
|
958e1b |
+{
|
|
|
958e1b |
+ uint64_t total_sectors;
|
|
|
958e1b |
+
|
|
|
958e1b |
+ bdrv_get_geometry(s->bs, &total_sectors);
|
|
|
958e1b |
+ if (sector > total_sectors || nb_sectors > total_sectors - sector) {
|
|
|
958e1b |
+ return false;
|
|
|
958e1b |
+ }
|
|
|
958e1b |
+ return true;
|
|
|
958e1b |
+}
|
|
|
958e1b |
+
|
|
|
958e1b |
static void ide_sector_read_cb(void *opaque, int ret)
|
|
|
958e1b |
{
|
|
|
958e1b |
IDEState *s = opaque;
|
|
|
958e1b |
@@ -568,6 +580,11 @@ void ide_sector_read(IDEState *s)
|
|
|
958e1b |
printf("sector=%" PRId64 "\n", sector_num);
|
|
|
958e1b |
#endif
|
|
|
958e1b |
|
|
|
958e1b |
+ if (!ide_sect_range_ok(s, sector_num, n)) {
|
|
|
958e1b |
+ ide_rw_error(s);
|
|
|
958e1b |
+ return;
|
|
|
958e1b |
+ }
|
|
|
958e1b |
+
|
|
|
958e1b |
s->iov.iov_base = s->io_buffer;
|
|
|
958e1b |
s->iov.iov_len = n * BDRV_SECTOR_SIZE;
|
|
|
958e1b |
qemu_iovec_init_external(&s->qiov, &s->iov, 1);
|
|
|
958e1b |
@@ -685,6 +702,12 @@ void ide_dma_cb(void *opaque, int ret)
|
|
|
958e1b |
sector_num, n, s->dma_cmd);
|
|
|
958e1b |
#endif
|
|
|
958e1b |
|
|
|
958e1b |
+ if (!ide_sect_range_ok(s, sector_num, n)) {
|
|
|
958e1b |
+ dma_buf_commit(s);
|
|
|
958e1b |
+ ide_dma_error(s);
|
|
|
958e1b |
+ return;
|
|
|
958e1b |
+ }
|
|
|
958e1b |
+
|
|
|
958e1b |
switch (s->dma_cmd) {
|
|
|
958e1b |
case IDE_DMA_READ:
|
|
|
958e1b |
s->bus->dma->aiocb = dma_bdrv_read(s->bs, &s->sg, sector_num,
|
|
|
958e1b |
@@ -804,6 +827,11 @@ void ide_sector_write(IDEState *s)
|
|
|
958e1b |
n = s->req_nb_sectors;
|
|
|
958e1b |
}
|
|
|
958e1b |
|
|
|
958e1b |
+ if (!ide_sect_range_ok(s, sector_num, n)) {
|
|
|
958e1b |
+ ide_rw_error(s);
|
|
|
958e1b |
+ return;
|
|
|
958e1b |
+ }
|
|
|
958e1b |
+
|
|
|
958e1b |
s->iov.iov_base = s->io_buffer;
|
|
|
958e1b |
s->iov.iov_len = n * BDRV_SECTOR_SIZE;
|
|
|
958e1b |
qemu_iovec_init_external(&s->qiov, &s->iov, 1);
|
|
|
958e1b |
--
|
|
|
958e1b |
1.8.3.1
|
|
|
958e1b |
|