yeahuh / rpms / qemu-kvm

Forked from rpms/qemu-kvm 2 years ago
Clone

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

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