From patchwork Tue May 3 16:29:39 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Laszlo Ersek X-Patchwork-Id: 67071 Delivered-To: patch@linaro.org Received: by 10.140.92.199 with SMTP id b65csp688673qge; Tue, 3 May 2016 09:29:48 -0700 (PDT) X-Received: by 10.98.99.66 with SMTP id x63mr4879564pfb.132.1462292988201; Tue, 03 May 2016 09:29:48 -0700 (PDT) Return-Path: Received: from ml01.01.org (ml01.01.org. [198.145.21.10]) by mx.google.com with ESMTPS id y134si6715pfb.59.2016.05.03.09.29.47 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Tue, 03 May 2016 09:29:48 -0700 (PDT) Received-SPF: pass (google.com: best guess record for domain of edk2-devel-bounces@lists.01.org designates 198.145.21.10 as permitted sender) client-ip=198.145.21.10; Authentication-Results: mx.google.com; spf=pass (google.com: best guess record for domain of edk2-devel-bounces@lists.01.org designates 198.145.21.10 as permitted sender) smtp.mailfrom=edk2-devel-bounces@lists.01.org Received: from [127.0.0.1] (localhost [IPv6:::1]) by ml01.01.org (Postfix) with ESMTP id 93E091A1E9D; Tue, 3 May 2016 09:29:47 -0700 (PDT) X-Original-To: edk2-devel@ml01.01.org Delivered-To: edk2-devel@ml01.01.org Received: from mx1.redhat.com (mx1.redhat.com [209.132.183.28]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ml01.01.org (Postfix) with ESMTPS id 975851A1E2E for ; Tue, 3 May 2016 09:29:45 -0700 (PDT) Received: from int-mx10.intmail.prod.int.phx2.redhat.com (int-mx10.intmail.prod.int.phx2.redhat.com [10.5.11.23]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 015A65F24; Tue, 3 May 2016 16:29:45 +0000 (UTC) Received: from lacos-laptop-7.usersys.redhat.com (ovpn-113-36.phx2.redhat.com [10.3.113.36]) by int-mx10.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id u43GTgt0008351; Tue, 3 May 2016 12:29:43 -0400 From: Laszlo Ersek To: edk2-devel-01 Date: Tue, 3 May 2016 18:29:39 +0200 Message-Id: <1462292979-12314-1-git-send-email-lersek@redhat.com> X-Scanned-By: MIMEDefang 2.68 on 10.5.11.23 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.38]); Tue, 03 May 2016 16:29:45 +0000 (UTC) Subject: [edk2] [PATCH] MdeModulePkg: ScsiDiskDxe: cope with broken "Supported VPD Pages" VPD page X-BeenThere: edk2-devel@lists.01.org X-Mailman-Version: 2.1.20 Precedence: list List-Id: EDK II Development List-Unsubscribe: , List-Post: List-Help: List-Subscribe: , Cc: Ruiyu Ni , Paolo Bonzini , Feng Tian , Star Zeng MIME-Version: 1.0 Errors-To: edk2-devel-bounces@lists.01.org Sender: "edk2-devel" The USB flash drive with Vendor ID 0x1516 (CompUSA) and Product ID 0x6221 returns a broken "Supported VPD Pages" VPD page. In particular, the PageLength field has the invalid value 0x0602 (decimal 1538). This prevents the loop from terminating that scans for the Block Limits VPD page code in ScsiDiskInquiryDevice(): for (Index = 0; Index < PageLength; Index++) { because the Index variable has type UINT8, and it wraps from 255 to 0, without ever reaching PageLength (1538), and because EFI_SCSI_PAGE_CODE_BLOCK_LIMITS_VPD does not occur at offsets 0 through 255. * The fix is not to change the type of Index to UINT16 or a wider type. Namely, section 7.8.14 Supported VPD Pages VPD page in the "SCSI Primary Commands - 4" (SPC-4) specification names the following requirement: The supported VPD page list shall contain a list of all VPD page codes (see 7.8) implemented by the logical unit in ascending order beginning with page code 00h. Since page codes are 8-bit unsigned quantities, it follows that the maximum size for the Supported VPD Pages VPD page is 0x100 bytes, in which every possible page code (0x00 through 0xFF) will be found, before the UINT8 offset wraps around. (EFI_SCSI_SUPPORTED_VPD_PAGES_VPD_PAGE.SupportedVpdPageList is correctly sized as well, in "MdePkg/Include/IndustryStandard/Scsi.h".) * Instead, add sanity checks that enforce the above requirement. If the device breaks the spec, simply fall back to the "Block Limits page absent" case. Cc: Feng Tian Cc: Paolo Bonzini Cc: Ruiyu Ni Cc: Star Zeng Ref: https://bugzilla.redhat.com/show_bug.cgi?id=1330955 Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Laszlo Ersek --- MdeModulePkg/Bus/Scsi/ScsiDiskDxe/ScsiDisk.c | 37 ++++++++++++++++++++ 1 file changed, 37 insertions(+) -- 1.8.3.1 _______________________________________________ edk2-devel mailing list edk2-devel@lists.01.org https://lists.01.org/mailman/listinfo/edk2-devel diff --git a/MdeModulePkg/Bus/Scsi/ScsiDiskDxe/ScsiDisk.c b/MdeModulePkg/Bus/Scsi/ScsiDiskDxe/ScsiDisk.c index dfa5fa32e635..1b75d55231a6 100644 --- a/MdeModulePkg/Bus/Scsi/ScsiDiskDxe/ScsiDisk.c +++ b/MdeModulePkg/Bus/Scsi/ScsiDiskDxe/ScsiDisk.c @@ -1493,7 +1493,44 @@ ScsiDiskInquiryDevice ( if (!EFI_ERROR (Status)) { PageLength = (SupportedVpdPages->PageLength2 << 8) | SupportedVpdPages->PageLength1; + + // + // Sanity checks for coping with broken devices + // + if (PageLength > sizeof SupportedVpdPages->SupportedVpdPageList) { + DEBUG ((EFI_D_WARN, + "%a: invalid PageLength (%u) in Supported VPD Pages page\n", + __FUNCTION__, (UINT32)PageLength)); + PageLength = 0; + } + + if ((PageLength > 0) && + (SupportedVpdPages->SupportedVpdPageList[0] != + EFI_SCSI_PAGE_CODE_SUPPORTED_VPD)) { + DEBUG ((EFI_D_WARN, + "%a: Supported VPD Pages page doesn't start with code 0x%02x\n", + __FUNCTION__, EFI_SCSI_PAGE_CODE_SUPPORTED_VPD)); + PageLength = 0; + } + + // + // Locate the code for the Block Limits VPD page + // for (Index = 0; Index < PageLength; Index++) { + // + // Sanity check + // + if ((Index > 0) && + (SupportedVpdPages->SupportedVpdPageList[Index] <= + SupportedVpdPages->SupportedVpdPageList[Index - 1])) { + DEBUG ((EFI_D_WARN, + "%a: non-ascending code in Supported VPD Pages page @ %u\n", + __FUNCTION__, Index)); + Index = 0; + PageLength = 0; + break; + } + if (SupportedVpdPages->SupportedVpdPageList[Index] == EFI_SCSI_PAGE_CODE_BLOCK_LIMITS_VPD) { break; }