Blame SOURCES/kvm-ide-atapi-check-logical-block-address-and-read-size-.patch

c687bc
From 0453588f95294ed5ce912cb8b810a322bf9d91e0 Mon Sep 17 00:00:00 2001
c687bc
From: Jon Maloy <jmaloy@redhat.com>
c687bc
Date: Thu, 25 Feb 2021 19:43:02 -0500
c687bc
Subject: [PATCH] ide: atapi: check logical block address and read size
c687bc
 (CVE-2020-29443)
c687bc
MIME-Version: 1.0
c687bc
Content-Type: text/plain; charset=UTF-8
c687bc
Content-Transfer-Encoding: 8bit
c687bc
c687bc
RH-Author: Jon Maloy <jmaloy@redhat.com>
c687bc
Message-id: <20210225194302.3137699-2-jmaloy@redhat.com>
c687bc
Patchwork-id: 101208
c687bc
O-Subject: [RHEL-8.4.0 qemu-kvm PATCH v2 1/1] ide: atapi: check logical block address and read size (CVE-2020-29443)
c687bc
Bugzilla: 1917451
c687bc
RH-Acked-by: Philippe Mathieu-Daudé <philmd@redhat.com>
c687bc
RH-Acked-by: Danilo de Paula <ddepaula@redhat.com>
c687bc
RH-Acked-by: Paolo Bonzini <pbonzini@redhat.com>
c687bc
c687bc
From: Prasad J Pandit <pjp@fedoraproject.org>
c687bc
c687bc
While processing ATAPI cmd_read/cmd_read_cd commands,
c687bc
Logical Block Address (LBA) maybe invalid OR closer to the last block,
c687bc
leading to an OOB access issues. Add range check to avoid it.
c687bc
c687bc
Fixes: CVE-2020-29443
c687bc
Reported-by: Wenxiang Qian <leonwxqian@gmail.com>
c687bc
Suggested-by: Paolo Bonzini <pbonzini@redhat.com>
c687bc
Reviewed-by: Paolo Bonzini <pbonzini@redhat.com>
c687bc
Signed-off-by: Prasad J Pandit <pjp@fedoraproject.org>
c687bc
Message-Id: <20210118115130.457044-1-ppandit@redhat.com>
c687bc
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
c687bc
c687bc
(cherry picked from commit b8d7f1bc59276fec85e4d09f1567613a3e14d31e)
c687bc
Signed-off-by: Jon Maloy <jmaloy@redhat.com>
c687bc
Signed-off-by: Danilo C. L. de Paula <ddepaula@redhat.com>
c687bc
---
c687bc
 hw/ide/atapi.c | 30 ++++++++++++++++++++++++------
c687bc
 1 file changed, 24 insertions(+), 6 deletions(-)
c687bc
c687bc
diff --git a/hw/ide/atapi.c b/hw/ide/atapi.c
c687bc
index 17a9d635d8..d064935c8d 100644
c687bc
--- a/hw/ide/atapi.c
c687bc
+++ b/hw/ide/atapi.c
c687bc
@@ -320,6 +320,8 @@ static void ide_atapi_cmd_reply(IDEState *s, int size, int max_size)
c687bc
 static void ide_atapi_cmd_read_pio(IDEState *s, int lba, int nb_sectors,
c687bc
                                    int sector_size)
c687bc
 {
c687bc
+    assert(0 <= lba && lba < (s->nb_sectors >> 2));
c687bc
+
c687bc
     s->lba = lba;
c687bc
     s->packet_transfer_size = nb_sectors * sector_size;
c687bc
     s->elementary_transfer_size = 0;
c687bc
@@ -418,6 +420,8 @@ eot:
c687bc
 static void ide_atapi_cmd_read_dma(IDEState *s, int lba, int nb_sectors,
c687bc
                                    int sector_size)
c687bc
 {
c687bc
+    assert(0 <= lba && lba < (s->nb_sectors >> 2));
c687bc
+
c687bc
     s->lba = lba;
c687bc
     s->packet_transfer_size = nb_sectors * sector_size;
c687bc
     s->io_buffer_size = 0;
c687bc
@@ -971,35 +975,49 @@ static void cmd_prevent_allow_medium_removal(IDEState *s, uint8_t* buf)
c687bc
 
c687bc
 static void cmd_read(IDEState *s, uint8_t* buf)
c687bc
 {
c687bc
-    int nb_sectors, lba;
c687bc
+    unsigned int nb_sectors, lba;
c687bc
+
c687bc
+    /* Total logical sectors of ATAPI_SECTOR_SIZE(=2048) bytes */
c687bc
+    uint64_t total_sectors = s->nb_sectors >> 2;
c687bc
 
c687bc
     if (buf[0] == GPCMD_READ_10) {
c687bc
         nb_sectors = lduw_be_p(buf + 7);
c687bc
     } else {
c687bc
         nb_sectors = ldl_be_p(buf + 6);
c687bc
     }
c687bc
-
c687bc
-    lba = ldl_be_p(buf + 2);
c687bc
     if (nb_sectors == 0) {
c687bc
         ide_atapi_cmd_ok(s);
c687bc
         return;
c687bc
     }
c687bc
 
c687bc
+    lba = ldl_be_p(buf + 2);
c687bc
+    if (lba >= total_sectors || lba + nb_sectors - 1 >= total_sectors) {
c687bc
+        ide_atapi_cmd_error(s, ILLEGAL_REQUEST, ASC_LOGICAL_BLOCK_OOR);
c687bc
+        return;
c687bc
+    }
c687bc
+
c687bc
     ide_atapi_cmd_read(s, lba, nb_sectors, 2048);
c687bc
 }
c687bc
 
c687bc
 static void cmd_read_cd(IDEState *s, uint8_t* buf)
c687bc
 {
c687bc
-    int nb_sectors, lba, transfer_request;
c687bc
+    unsigned int nb_sectors, lba, transfer_request;
c687bc
 
c687bc
-    nb_sectors = (buf[6] << 16) | (buf[7] << 8) | buf[8];
c687bc
-    lba = ldl_be_p(buf + 2);
c687bc
+    /* Total logical sectors of ATAPI_SECTOR_SIZE(=2048) bytes */
c687bc
+    uint64_t total_sectors = s->nb_sectors >> 2;
c687bc
 
c687bc
+    nb_sectors = (buf[6] << 16) | (buf[7] << 8) | buf[8];
c687bc
     if (nb_sectors == 0) {
c687bc
         ide_atapi_cmd_ok(s);
c687bc
         return;
c687bc
     }
c687bc
 
c687bc
+    lba = ldl_be_p(buf + 2);
c687bc
+    if (lba >= total_sectors || lba + nb_sectors - 1 >= total_sectors) {
c687bc
+        ide_atapi_cmd_error(s, ILLEGAL_REQUEST, ASC_LOGICAL_BLOCK_OOR);
c687bc
+        return;
c687bc
+    }
c687bc
+
c687bc
     transfer_request = buf[9] & 0xf8;
c687bc
     if (transfer_request == 0x00) {
c687bc
         /* nothing */
c687bc
-- 
c687bc
2.27.0
c687bc