From patchwork Fri Apr 18 21:04:22 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Rodrigo Vivi X-Patchwork-Id: 4018531 Return-Path: X-Original-To: patchwork-intel-gfx@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork2.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.19.201]) by patchwork2.web.kernel.org (Postfix) with ESMTP id 05284BFF02 for ; Fri, 18 Apr 2014 21:04:47 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id 2CE79203AB for ; Fri, 18 Apr 2014 21:04:46 +0000 (UTC) Received: from gabe.freedesktop.org (gabe.freedesktop.org [131.252.210.177]) by mail.kernel.org (Postfix) with ESMTP id 5D9B7202E6 for ; Fri, 18 Apr 2014 21:04:45 +0000 (UTC) Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id 01F716ECF2; Fri, 18 Apr 2014 14:04:45 -0700 (PDT) X-Original-To: intel-gfx@lists.freedesktop.org Delivered-To: intel-gfx@lists.freedesktop.org Received: from mail-pd0-f178.google.com (mail-pd0-f178.google.com [209.85.192.178]) by gabe.freedesktop.org (Postfix) with ESMTP id 3331E6ECF1 for ; Fri, 18 Apr 2014 14:04:42 -0700 (PDT) Received: by mail-pd0-f178.google.com with SMTP id x10so1766578pdj.23 for ; Fri, 18 Apr 2014 14:04:42 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=NW2pH6G/gRoVCuj+3IGIGG4uYqJCp9bGslthtKaZwgM=; b=jNwvCj4GHE3NFytXw7DUsyvHYGB8bz8PDkxJymDnO1xG1xmBouVApc/I2J54BYaJun 3oruDvs7fRAaBLgE8AiRnhjUicGrpQIqI7iiDQ3T24Vmpt8raCsuMNxqaysTRcE3WUzG Gs0aQeHFUBj3laaMQ0kHQvYJ+Xnzm+Cj+N6L2kdJbV5q+MsbM3/C3MIhD2NLVAGkclel 0bUrG8TROoIVt52Zp6mLBZ2quMlRtaL5kotBU3AAZKqRlyVNb2NuoDCa6U6HBy4QKYPX 3ZiCo+DUvvvtkxA/gV0PJ35FOFS4Y9nb/1sFTG/vEPamB/nNBv2UQ23FFBxHoS3nouXq YXOA== X-Received: by 10.68.163.100 with SMTP id yh4mr24300824pbb.122.1397855082065; Fri, 18 Apr 2014 14:04:42 -0700 (PDT) Received: from localhost (jfdmzpr03-ext.jf.intel.com. [134.134.139.72]) by mx.google.com with ESMTPSA id vd8sm146516414pac.12.2014.04.18.14.04.40 for (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Fri, 18 Apr 2014 14:04:41 -0700 (PDT) From: Rodrigo Vivi To: intel-gfx@lists.freedesktop.org Date: Fri, 18 Apr 2014 18:04:22 -0300 Message-Id: <1397855070-4480-7-git-send-email-rodrigo.vivi@gmail.com> X-Mailer: git-send-email 1.8.3.1 In-Reply-To: <1397855070-4480-1-git-send-email-rodrigo.vivi@gmail.com> References: <1397855070-4480-1-git-send-email-rodrigo.vivi@gmail.com> Subject: [Intel-gfx] [PATCH 06/14] drm/i915: Validate VBT header before trusting it X-BeenThere: intel-gfx@lists.freedesktop.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: Intel graphics driver community testing & development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Errors-To: intel-gfx-bounces@lists.freedesktop.org Sender: "Intel-gfx" X-Spam-Status: No, score=-4.7 required=5.0 tests=BAYES_00, DKIM_ADSP_CUSTOM_MED, DKIM_SIGNED, FREEMAIL_FROM, RCVD_IN_DNSWL_MED, RP_MATCHES_RCVD, T_DKIM_INVALID, UNPARSEABLE_RELAY autolearn=ham version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on mail.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP From: Chris Wilson Be we read and chase pointers from the VBT, it is prudent to make sure that those accesses are wholly contained within the MMIO region, or else we may cause a kernel panic during boot. Signed-off-by: Chris Wilson Signed-off-by: Rodrigo Vivi Reviewed-by: Shobhit Kumar --- drivers/gpu/drm/i915/intel_bios.c | 68 ++++++++++++++++++++++++++++----------- 1 file changed, 50 insertions(+), 18 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_bios.c b/drivers/gpu/drm/i915/intel_bios.c index fba9efd..fc9e806 100644 --- a/drivers/gpu/drm/i915/intel_bios.c +++ b/drivers/gpu/drm/i915/intel_bios.c @@ -1099,6 +1099,46 @@ static const struct dmi_system_id intel_no_opregion_vbt[] = { { } }; +static struct bdb_header *validate_vbt(char *base, size_t size, + struct vbt_header *vbt, + const char *source) +{ + size_t offset; + struct bdb_header *bdb; + + if (vbt == NULL) { + DRM_DEBUG_DRIVER("VBT signature missing\n"); + return NULL; + } + + offset = (char *)vbt - base; + if (offset + sizeof(struct vbt_header) > size) { + DRM_DEBUG_DRIVER("VBT header incomplete\n"); + return NULL; + } + + if (memcmp(vbt->signature, "$VBT", 4)) { + DRM_DEBUG_DRIVER("VBT invalid signature\n"); + return NULL; + } + + offset += vbt->bdb_offset; + if (offset + sizeof(struct bdb_header) > size) { + DRM_DEBUG_DRIVER("BDB header incomplete\n"); + return NULL; + } + + bdb = (struct bdb_header *)(base + offset); + if (offset + bdb->bdb_size > size) { + DRM_DEBUG_DRIVER("BDB incomplete\n"); + return NULL; + } + + DRM_DEBUG_KMS("Using VBT from %s: %20s\n", + source, vbt->signature); + return bdb; +} + /** * intel_parse_bios - find VBT and initialize settings from the BIOS * @dev: DRM device @@ -1122,20 +1162,13 @@ intel_parse_bios(struct drm_device *dev) init_vbt_defaults(dev_priv); /* XXX Should this validation be moved to intel_opregion.c? */ - if (!dmi_check_system(intel_no_opregion_vbt) && dev_priv->opregion.vbt) { - struct vbt_header *vbt = dev_priv->opregion.vbt; - if (memcmp(vbt->signature, "$VBT", 4) == 0) { - DRM_DEBUG_KMS("Using VBT from OpRegion: %20s\n", - vbt->signature); - bdb = (struct bdb_header *)((char *)vbt + vbt->bdb_offset); - } else - dev_priv->opregion.vbt = NULL; - } + if (!dmi_check_system(intel_no_opregion_vbt) && dev_priv->opregion.vbt) + bdb = validate_vbt((char *)dev_priv->opregion.header, OPREGION_SIZE, + (struct vbt_header *)dev_priv->opregion.vbt, + "OpRegion"); if (bdb == NULL) { - struct vbt_header *vbt = NULL; - size_t size; - int i; + size_t i, size; bios = pci_map_rom(pdev, &size); if (!bios) @@ -1143,19 +1176,18 @@ intel_parse_bios(struct drm_device *dev) /* Scour memory looking for the VBT signature */ for (i = 0; i + 4 < size; i++) { - if (!memcmp(bios + i, "$VBT", 4)) { - vbt = (struct vbt_header *)(bios + i); + if (memcmp(bios + i, "$VBT", 4) == 0) { + bdb = validate_vbt(bios, size, + (struct vbt_header *)(bios + i), + "PCI ROM"); break; } } - if (!vbt) { - DRM_DEBUG_DRIVER("VBT signature missing\n"); + if (!bdb) { pci_unmap_rom(pdev, bios); return -1; } - - bdb = (struct bdb_header *)(bios + i + vbt->bdb_offset); } /* Grab useful general definitions */