Received: by 2002:a05:6a10:f347:0:0:0:0 with SMTP id d7csp224196pxu; Wed, 25 Nov 2020 01:11:32 -0800 (PST) X-Google-Smtp-Source: ABdhPJxMxLtBVFRrS4Je0tE0eDknm2dl3JJxEpXDg/PCtdyiyScr3+aumXEYB3bl0vKpLPO0lL9h X-Received: by 2002:aa7:cdc1:: with SMTP id h1mr1760315edw.156.1606295492150; Wed, 25 Nov 2020 01:11:32 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1606295492; cv=none; d=google.com; s=arc-20160816; b=bZ8pejox+CfnGaCLydBTsrw5rhQD/1waON/s9J0mKmCv2vVgRJY6G8nh7U2o4ODmej AFscelfUWK/zGMvKNLt6wwk21AzBClFAsdim42KAXwB0ghNzWAdD3IAbueKOdY9pXONe fuYWCoUy/RWvTe8PVbiS08Nn/cMu7dSQLTxQQOcrJc0PP86DhoUy66VJ6GvekMuNsfmJ Jz5agouOP1/yzSUqDo+NlV6ZL2z3JvW99DHzBWDTfAwNUWUI5Qlsa0cMpWIC/NNKgXG1 N1HVCk3DH1NjSFQbcIVB6YeKORV0CmY0Q1WGNAphpdanT3vDqed+XdrgLNsBZs/7urG9 XjYg== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:mime-version:message-id:date:subject:cc:to:from; bh=KBa7Fd0tJJxP0pZYNpgZwG9/9lAIi2YnDv6wLRSF5ao=; b=TkI/nld+Bakk+T1rROGAC7dHwNLQXIhSARDe/n5LhpDQJOV3rQoUPvLFTatfx1AXxQ kqwVVwu8nD6Hi1kg/Ki8R6IdkfqCOprmL9vgCX1ohsy4QTx3SnqmfDzYtw4lwdUGHfVi BgFXCwZBbB5A4XR6kBblkCeRt0ZHgXCGUPSUo1uCRokf8JI5HoL9S9hsOiYCKL2aaQXJ 87meeys6FUpC/ejccT6eX9+O8KIPKy7T2iUf5UMe+p1xcSJku6+0E5951RHRIdMDruTq mBrfzlOMQpljyjkWLmDpnD0XsGeqnZik2Z4e2x1PDYc/54G9RBkbHHtVNv4MV5jddPaA gs6Q== ARC-Authentication-Results: i=1; mx.google.com; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [23.128.96.18]) by mx.google.com with ESMTP id j12si836633edy.584.2020.11.25.01.11.09; Wed, 25 Nov 2020 01:11:32 -0800 (PST) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) client-ip=23.128.96.18; Authentication-Results: mx.google.com; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726871AbgKYJJk (ORCPT + 99 others); Wed, 25 Nov 2020 04:09:40 -0500 Received: from twspam01.aspeedtech.com ([211.20.114.71]:41755 "EHLO twspam01.aspeedtech.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726284AbgKYJJj (ORCPT ); Wed, 25 Nov 2020 04:09:39 -0500 Received: from mail.aspeedtech.com ([192.168.0.24]) by twspam01.aspeedtech.com with ESMTP id 0AP94FrV071855; Wed, 25 Nov 2020 17:04:15 +0800 (GMT-8) (envelope-from kuohsiang_chou@aspeedtech.com) Received: from localhost.localdomain.com (192.168.2.206) by TWMBX02.aspeed.com (192.168.0.24) with Microsoft SMTP Server (TLS) id 15.0.1497.2; Wed, 25 Nov 2020 17:09:14 +0800 From: KuoHsiang Chou To: , , CC: , , , , , , Subject: [PATCH] drm/ast: Fixed CVE for DP501 Date: Wed, 25 Nov 2020 17:09:03 +0800 Message-ID: <20201125090903.4436-1-kuohsiang_chou@aspeedtech.com> X-Mailer: git-send-email 2.18.4 MIME-Version: 1.0 Content-Type: text/plain X-Originating-IP: [192.168.2.206] X-ClientProxiedBy: TWMBX02.aspeed.com (192.168.0.24) To TWMBX02.aspeed.com (192.168.0.24) X-DNSRBL: X-MAIL: twspam01.aspeedtech.com 0AP94FrV071855 Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org [Bug][DP501] 1. For security concerning, P2A have to be disabled by CVE regulation. 2. FrameBuffer reverses last 2MB used for the image of DP501. 3. If P2A is disallowed, the default "ioremap()" behavior is non-cached and could be an alternative accessing on the image of DP501. --- drivers/gpu/drm/ast/ast_dp501.c | 131 +++++++++++++++++++++++--------- drivers/gpu/drm/ast/ast_drv.h | 2 + drivers/gpu/drm/ast/ast_main.c | 12 +++ drivers/gpu/drm/ast/ast_mm.c | 1 + 4 files changed, 110 insertions(+), 36 deletions(-) diff --git a/drivers/gpu/drm/ast/ast_dp501.c b/drivers/gpu/drm/ast/ast_dp501.c index 88121c0e0d05..7640364ef2bc 100644 --- a/drivers/gpu/drm/ast/ast_dp501.c +++ b/drivers/gpu/drm/ast/ast_dp501.c @@ -189,6 +189,8 @@ bool ast_backup_fw(struct drm_device *dev, u8 *addr, u32 size) u32 i, data; u32 boot_address; + if (ast->config_mode != ast_use_p2a) return false; + data = ast_mindwm(ast, 0x1e6e2100) & 0x01; if (data) { boot_address = get_fw_base(ast); @@ -207,6 +209,8 @@ static bool ast_launch_m68k(struct drm_device *dev) u8 *fw_addr = NULL; u8 jreg; + if (ast->config_mode != ast_use_p2a) return false; + data = ast_mindwm(ast, 0x1e6e2100) & 0x01; if (!data) { @@ -272,24 +276,51 @@ u8 ast_get_dp501_max_clk(struct drm_device *dev) u32 boot_address, offset, data; u8 linkcap[4], linkrate, linklanes, maxclk = 0xff; - boot_address = get_fw_base(ast); - - /* validate FW version */ - offset = 0xf000; - data = ast_mindwm(ast, boot_address + offset); - if ((data & 0xf0) != 0x10) /* version: 1x */ - return maxclk; - - /* Read Link Capability */ - offset = 0xf014; - *(u32 *)linkcap = ast_mindwm(ast, boot_address + offset); - if (linkcap[2] == 0) { - linkrate = linkcap[0]; - linklanes = linkcap[1]; - data = (linkrate == 0x0a) ? (90 * linklanes) : (54 * linklanes); - if (data > 0xff) - data = 0xff; - maxclk = (u8)data; + if (ast->config_mode == ast_use_p2a) { + boot_address = get_fw_base(ast); + + /* validate FW version */ + offset = 0xf000; + data = ast_mindwm(ast, boot_address + offset); + if ((data & 0xf0) != 0x10) /* version: 1x */ + return maxclk; + + /* Read Link Capability */ + offset = 0xf014; + *(u32 *)linkcap = ast_mindwm(ast, boot_address + offset); + if (linkcap[2] == 0) { + linkrate = linkcap[0]; + linklanes = linkcap[1]; + data = (linkrate == 0x0a) ? (90 * linklanes) : (54 * linklanes); + if (data > 0xff) + data = 0xff; + maxclk = (u8)data; + } + } + else { + if (!ast->reservedbuffer) return 65; /* 1024x768 as default */ + + /* dummy read */ + offset = 0x0000; + data = *(u32 *) (ast->reservedbuffer + offset); + + /* validate FW version */ + offset = 0xf000; + data = *(u32 *) (ast->reservedbuffer + offset); + if ((data & 0xf0) != 0x10) /* version: 1x */ + return maxclk; + + /* Read Link Capability */ + offset = 0xf014; + *(u32 *)linkcap = *(u32 *) (ast->reservedbuffer + offset); + if (linkcap[2] == 0) { + linkrate = linkcap[0]; + linklanes = linkcap[1]; + data = (linkrate == 0x0a) ? (90 * linklanes) : (54 * linklanes); + if (data > 0xff) + data = 0xff; + maxclk = (u8)data; + } } return maxclk; } @@ -299,25 +330,53 @@ bool ast_dp501_read_edid(struct drm_device *dev, u8 *ediddata) struct ast_private *ast = to_ast_private(dev); u32 i, boot_address, offset, data; - boot_address = get_fw_base(ast); - - /* validate FW version */ - offset = 0xf000; - data = ast_mindwm(ast, boot_address + offset); - if ((data & 0xf0) != 0x10) - return false; - - /* validate PnP Monitor */ - offset = 0xf010; - data = ast_mindwm(ast, boot_address + offset); - if (!(data & 0x01)) - return false; + if (ast->config_mode == ast_use_p2a) { + boot_address = get_fw_base(ast); - /* Read EDID */ - offset = 0xf020; - for (i = 0; i < 128; i += 4) { - data = ast_mindwm(ast, boot_address + offset + i); - *(u32 *)(ediddata + i) = data; + /* validate FW version */ + offset = 0xf000; + data = ast_mindwm(ast, boot_address + offset); + if ((data & 0xf0) != 0x10) + return false; + + /* validate PnP Monitor */ + offset = 0xf010; + data = ast_mindwm(ast, boot_address + offset); + if (!(data & 0x01)) + return false; + + /* Read EDID */ + offset = 0xf020; + for (i = 0; i < 128; i += 4) { + data = ast_mindwm(ast, boot_address + offset + i); + *(u32 *)(ediddata + i) = data; + } + } + else { + if (!ast->reservedbuffer) return false; + + /* dummy read */ + offset = 0x0000; + data = *(u32 *) (ast->reservedbuffer + offset); + + /* validate FW version */ + offset = 0xf000; + data = *(u32 *) (ast->reservedbuffer + offset); + if ((data & 0xf0) != 0x10) + return false; + + /* validate PnP Monitor */ + offset = 0xf010; + data = *(u32 *) (ast->reservedbuffer + offset); + if (!(data & 0x01)) + return false; + + /* Read EDID */ + offset = 0xf020; + for (i = 0; i < 128; i+=4) { + data = *(u32 *) (ast->reservedbuffer + offset + i); + *(u32 *)(ediddata + i) = data; + } } return true; diff --git a/drivers/gpu/drm/ast/ast_drv.h b/drivers/gpu/drm/ast/ast_drv.h index 6b9e3b94a712..cd17e0683fd7 100644 --- a/drivers/gpu/drm/ast/ast_drv.h +++ b/drivers/gpu/drm/ast/ast_drv.h @@ -121,12 +121,14 @@ struct ast_private { void __iomem *regs; void __iomem *ioregs; + void __iomem *reservedbuffer; enum ast_chip chip; bool vga2_clone; uint32_t dram_bus_width; uint32_t dram_type; uint32_t mclk; + uint32_t vram_size; int fb_mtrr; diff --git a/drivers/gpu/drm/ast/ast_main.c b/drivers/gpu/drm/ast/ast_main.c index 4ec6884f6c65..4477b4cf1b06 100644 --- a/drivers/gpu/drm/ast/ast_main.c +++ b/drivers/gpu/drm/ast/ast_main.c @@ -393,6 +393,7 @@ static void ast_device_release(void *data) /* enable standard VGA decode */ ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0xa1, 0x04); + pci_iounmap(ast->base.pdev, ast->reservedbuffer); } struct ast_private *ast_device_create(struct drm_driver *drv, @@ -449,6 +450,17 @@ struct ast_private *ast_device_create(struct drm_driver *drv, if (ret) return ERR_PTR(ret); + /* map reserved buffer */ + ast->reservedbuffer = NULL; + if (ast->vram_size < pci_resource_len(dev->pdev, 0)) { + ast->reservedbuffer = ioremap( \ + pci_resource_start(ast->base.pdev, 0) + (unsigned long)ast->vram_size, \ + pci_resource_len(dev->pdev, 0) - ast->vram_size); + if (!ast->reservedbuffer) { + DRM_INFO("failed to map reserved buffer! \n"); + } + } + ret = ast_mode_config_init(ast); if (ret) return ERR_PTR(ret); diff --git a/drivers/gpu/drm/ast/ast_mm.c b/drivers/gpu/drm/ast/ast_mm.c index 8392ebde504b..c6fd24493fb3 100644 --- a/drivers/gpu/drm/ast/ast_mm.c +++ b/drivers/gpu/drm/ast/ast_mm.c @@ -90,6 +90,7 @@ int ast_mm_init(struct ast_private *ast) int ret; vram_size = ast_get_vram_size(ast); + ast->vram_size = (uint32_t) vram_size; ret = drmm_vram_helper_init(dev, pci_resource_start(dev->pdev, 0), vram_size); -- 2.18.4