Received: by 2002:ac0:a594:0:0:0:0:0 with SMTP id m20-v6csp6015036imm; Sat, 19 May 2018 15:09:46 -0700 (PDT) X-Google-Smtp-Source: AB8JxZoycOLTzyorXq0GuZaFCxEduJ4Cf8mNjcD0TremgftUoFIE8rf7QnF7LyIZ3FeB8I5scKeu X-Received: by 2002:a65:65d2:: with SMTP id y18-v6mr11154369pgv.186.1526767786074; Sat, 19 May 2018 15:09:46 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1526767786; cv=none; d=google.com; s=arc-20160816; b=GTl0qTSPuwahsSvrjzwOk3KQu84mrA5udzBSOcjgNTjSH1nXARuR47NUmRLxddT3pW Csw17E1c/DVViApndHpFdESQoktK9LcaYw5RPyQ+E+NGVWO9gCfRbH9opGi6jhcWpDMQ tVvF9H/KMnFN45TSiBzP/TayvjAFdRPnWUIY4wylwStOVp2UvpOhqf1nOKfKmfhjA4S7 AaJ2u6CtUqTqg8QLIdvIyt9HSb7+0EEI/nK7cArmThTe5aDaWpflSDCaspY8vjVz2dKW qRSeOiRwmBKNLiPNnt4K9xzcxcnXkBX63QZT6VcgbHGb2OC0mUlCaHZGyXKFWRmS2ek7 Przw== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:references:in-reply-to:message-id:date :subject:cc:to:from:arc-authentication-results; bh=wmdmNY0GZ9hXZjkfSZ3TiWXJ+oIULmWtmeuBOmDGA90=; b=FCBguoYmsvdb+/pwQHOFSdEtHOeDEb2smPSjzq5iqW1Wt2Ca1KK56NObVKjK/OUycK VEA4UPnwRxtgOisfP77Bn3JgMqgg0UxCRwNTOOaJMVFRQr8A9Fp1MQNx7Stok+Q4ElD7 pi3xeYeKD1lC17qTm+hcGJvjzVtSHDaSblMzHZlcgmG1E9j3stTIUnTrUq2j9MRXupWK 63YUW/9RgqOkRkgIwKaDbQiaAUI6N+39KC8aL7dDhXB4QY+9yGnAaPp5RoOK61aeT0Qs JYMQk9tLnq3j5lcDHp11i0B1/O24dbLoZvZjMwJPT28mOejDergepfBMtEMHCgdnQ03D Kw6Q== ARC-Authentication-Results: i=1; mx.google.com; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id y3-v6si8359557pgv.571.2018.05.19.15.09.31; Sat, 19 May 2018 15:09:46 -0700 (PDT) Received-SPF: pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1752727AbeESWIe (ORCPT + 99 others); Sat, 19 May 2018 18:08:34 -0400 Received: from vps-vb.mhejs.net ([37.28.154.113]:49448 "EHLO vps-vb.mhejs.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1752594AbeESWHs (ORCPT ); Sat, 19 May 2018 18:07:48 -0400 Received: by vps-vb.mhejs.net with esmtps (TLSv1.2:ECDHE-RSA-AES256-GCM-SHA384:256) (Exim 4.90_1) (envelope-from ) id 1fKA0a-0001PE-PA; Sun, 20 May 2018 00:07:24 +0200 From: "Maciej S. Szmigiero" To: Borislav Petkov Cc: Thomas Gleixner , Ingo Molnar , "H. Peter Anvin" , x86@kernel.org, linux-kernel@vger.kernel.org Subject: [PATCH v6 8/8] x86/microcode/AMD: Don't scan past the CPU equivalence table data Date: Sun, 20 May 2018 00:07:22 +0200 Message-Id: <04a252b1e06673b8a1f62196093d0573d302fc1b.1526767245.git.mail@maciej.szmigiero.name> X-Mailer: git-send-email 2.17.0 In-Reply-To: References: Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Currently, the code scanning a CPU equivalence table read from a microcode container file assumes that it actually contains a terminating zero entry, but if does not then the code will continue the scan past its valid data. For the late loader this can be improved by always appending a terminating zero entry to such table when loading it. This way we don't need an extra global variable for holding the table size and we don't have to reject such incomplete tables (for backward compatibility with the existing code which didn't do so). For the early loader, since we can't allocate memory and have to work in-place, let's pass an explicit size of this table to its scanning functions so they will know when to stop. Signed-off-by: Maciej S. Szmigiero --- arch/x86/kernel/cpu/microcode/amd.c | 46 ++++++++++++++++++++++------- 1 file changed, 36 insertions(+), 10 deletions(-) diff --git a/arch/x86/kernel/cpu/microcode/amd.c b/arch/x86/kernel/cpu/microcode/amd.c index cc38182c76d2..f443aede50d5 100644 --- a/arch/x86/kernel/cpu/microcode/amd.c +++ b/arch/x86/kernel/cpu/microcode/amd.c @@ -63,12 +63,18 @@ static u8 amd_ucode_patch[PATCH_MAX_SIZE]; static const char ucode_path[] __maybe_unused = "kernel/x86/microcode/AuthenticAMD.bin"; -static u16 find_equiv_id(struct equiv_cpu_entry *equiv_table, u32 sig) +static u16 find_equiv_id(const struct equiv_cpu_entry *equiv_table, + unsigned int equiv_table_entries, u32 sig) { - for (; equiv_table && equiv_table->installed_cpu; equiv_table++) { - if (sig == equiv_table->installed_cpu) - return equiv_table->equiv_cpu; - } + unsigned int i; + + if (!equiv_table) + return 0; + + for (i = 0; i < equiv_table_entries && equiv_table[i].installed_cpu; + i++) + if (sig == equiv_table[i].installed_cpu) + return equiv_table[i].equiv_cpu; return 0; } @@ -273,7 +279,8 @@ static size_t parse_container(u8 *ucode, size_t size, struct cont_desc *desc) eq = (struct equiv_cpu_entry *)(buf + CONTAINER_HDR_SZ); /* Find the equivalence ID of our CPU in this table: */ - eq_id = find_equiv_id(eq, desc->cpuid_1_eax); + eq_id = find_equiv_id(eq, equiv_tbl_len / sizeof(*eq), + desc->cpuid_1_eax); buf += CONTAINER_HDR_SZ; buf += equiv_tbl_len; @@ -540,12 +547,14 @@ void reload_ucode_amd(void) static u16 __find_equiv_id(unsigned int cpu) { struct ucode_cpu_info *uci = ucode_cpu_info + cpu; - return find_equiv_id(equiv_cpu_table, uci->cpu_sig.sig); + + /* install_equiv_cpu_table() guarantees us a terminating entry */ + return find_equiv_id(equiv_cpu_table, UINT_MAX, uci->cpu_sig.sig); } static u32 find_cpu_family_by_equiv_cpu(u16 equiv_cpu) { - int i = 0; + unsigned int i = 0; BUG_ON(!equiv_cpu_table); @@ -683,20 +692,37 @@ static unsigned int install_equiv_cpu_table(const u8 *buf, size_t buf_size) { const u32 *hdr; u32 equiv_tbl_len; + unsigned int equiv_tbl_entries; + const unsigned int equiv_tbl_entries_max = + UINT_MAX / sizeof(struct equiv_cpu_entry); if (!verify_equivalence_table(buf, buf_size, false)) return 0; hdr = (const u32 *)buf; equiv_tbl_len = hdr[2]; + equiv_tbl_entries = equiv_tbl_len / sizeof(struct equiv_cpu_entry); - equiv_cpu_table = vmalloc(equiv_tbl_len); + /* + * Make space for a terminating entry. If there is no space left we + * reuse the last entry instead. + */ + if (equiv_tbl_entries < equiv_tbl_entries_max) + equiv_tbl_entries++; + + equiv_cpu_table = vmalloc(equiv_tbl_entries * + sizeof(struct equiv_cpu_entry)); if (!equiv_cpu_table) { pr_err("failed to allocate equivalent CPU table\n"); return 0; } - memcpy(equiv_cpu_table, buf + CONTAINER_HDR_SZ, equiv_tbl_len); + memcpy(equiv_cpu_table, buf + CONTAINER_HDR_SZ, + (equiv_tbl_entries - 1) * sizeof(struct equiv_cpu_entry)); + + /* Set up the terminating entry. */ + memset(&equiv_cpu_table[equiv_tbl_entries - 1], 0, + sizeof(struct equiv_cpu_entry)); return equiv_tbl_len; }