From patchwork Mon Mar 23 10:17:23 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Andrew Cooper X-Patchwork-Id: 11452619 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 8569F159A for ; Mon, 23 Mar 2020 10:19:29 +0000 (UTC) Received: from lists.xenproject.org (lists.xenproject.org [192.237.175.120]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 55D1C20722 for ; Mon, 23 Mar 2020 10:19:29 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=fail reason="signature verification failed" (1024-bit key) header.d=citrix.com header.i=@citrix.com header.b="AI1fMvmy" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 55D1C20722 Authentication-Results: mail.kernel.org; dmarc=fail (p=none dis=none) header.from=citrix.com Authentication-Results: mail.kernel.org; spf=pass smtp.mailfrom=xen-devel-bounces@lists.xenproject.org Received: from localhost ([127.0.0.1] helo=lists.xenproject.org) by lists.xenproject.org with esmtp (Exim 4.89) (envelope-from ) id 1jGK9h-0007hC-La; Mon, 23 Mar 2020 10:18:01 +0000 Received: from all-amaz-eas1.inumbo.com ([34.197.232.57] helo=us1-amaz-eas2.inumbo.com) by lists.xenproject.org with esmtp (Exim 4.89) (envelope-from ) id 1jGK9f-0007g5-Ip for xen-devel@lists.xenproject.org; Mon, 23 Mar 2020 10:17:59 +0000 X-Inumbo-ID: 917515f0-6cef-11ea-829d-12813bfff9fa Received: from esa5.hc3370-68.iphmx.com (unknown [216.71.155.168]) by us1-amaz-eas2.inumbo.com (Halon) with ESMTPS id 917515f0-6cef-11ea-829d-12813bfff9fa; Mon, 23 Mar 2020 10:17:58 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=simple/simple; d=citrix.com; s=securemail; t=1584958678; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=Sxrnn/HeXrku8q3Uxl6x5vwRPlCId0vHiJDnUachLKs=; b=AI1fMvmyXgJJ+EhVY+VxJvuu5UHWNDCAXyjjJvZk8tbt+nwWN8XNu73J jQieYs1mA9PwTOTCyzOcRxhSUn/f1GpT/bKkANCcttAgAyKEG3zzLeosl NN/daXGth3qYMf5BJdwhp2DF7Y51tO/+HAWRsgbfVptOxMq6G4/zHHM1E w=; Authentication-Results: esa5.hc3370-68.iphmx.com; dkim=none (message not signed) header.i=none; spf=None smtp.pra=andrew.cooper3@citrix.com; spf=Pass smtp.mailfrom=Andrew.Cooper3@citrix.com; spf=None smtp.helo=postmaster@mail.citrix.com Received-SPF: None (esa5.hc3370-68.iphmx.com: no sender authenticity information available from domain of andrew.cooper3@citrix.com) identity=pra; client-ip=162.221.158.21; receiver=esa5.hc3370-68.iphmx.com; envelope-from="Andrew.Cooper3@citrix.com"; x-sender="andrew.cooper3@citrix.com"; x-conformance=sidf_compatible Received-SPF: Pass (esa5.hc3370-68.iphmx.com: domain of Andrew.Cooper3@citrix.com designates 162.221.158.21 as permitted sender) identity=mailfrom; client-ip=162.221.158.21; receiver=esa5.hc3370-68.iphmx.com; envelope-from="Andrew.Cooper3@citrix.com"; x-sender="Andrew.Cooper3@citrix.com"; x-conformance=sidf_compatible; x-record-type="v=spf1"; x-record-text="v=spf1 ip4:209.167.231.154 ip4:178.63.86.133 ip4:195.66.111.40/30 ip4:85.115.9.32/28 ip4:199.102.83.4 ip4:192.28.146.160 ip4:192.28.146.107 ip4:216.52.6.88 ip4:216.52.6.188 ip4:162.221.158.21 ip4:162.221.156.83 ip4:168.245.78.127 ~all" Received-SPF: None (esa5.hc3370-68.iphmx.com: no sender authenticity information available from domain of postmaster@mail.citrix.com) identity=helo; client-ip=162.221.158.21; receiver=esa5.hc3370-68.iphmx.com; envelope-from="Andrew.Cooper3@citrix.com"; x-sender="postmaster@mail.citrix.com"; x-conformance=sidf_compatible IronPort-SDR: O9D3cZ3CyTubtCl/3yyBugdPbrryv9m1z6uZ8fS/Lx/iIuT4VMtjXrH6iJ+4chpiPS0ItyzPtt LZP5mChQCXrxB1daYh7jdA1C9bqBS6ZPbqANirvj+jcPhjHEejEgCGzwFdJvjjjVd/++dn1q/d Z51rcD+0YpclDytECYrZ+WM2stze2S2vOpBKcXUu/SN4DddDDJaWrN+SUB8FQYbdQ8RgOxU/QW tJoSk2bf7P09ucttqBfe0T9qmrI+Tu6MQpWhO6mScbHDcVCeC+QpbTBIr76PhA3jXfyUBKoqjP mWc= X-SBRS: 2.7 X-MesageID: 14788287 X-Ironport-Server: esa5.hc3370-68.iphmx.com X-Remote-IP: 162.221.158.21 X-Policy: $RELAYED X-IronPort-AV: E=Sophos;i="5.72,296,1580792400"; d="scan'208";a="14788287" From: Andrew Cooper To: Xen-devel Date: Mon, 23 Mar 2020 10:17:23 +0000 Message-ID: <20200323101724.15655-7-andrew.cooper3@citrix.com> X-Mailer: git-send-email 2.11.0 In-Reply-To: <20200323101724.15655-1-andrew.cooper3@citrix.com> References: <20200323101724.15655-1-andrew.cooper3@citrix.com> MIME-Version: 1.0 Subject: [Xen-devel] [PATCH 6/7] x86/ucode/intel: Clean up microcode_sanity_check() X-BeenThere: xen-devel@lists.xenproject.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: Xen developer discussion List-Unsubscribe: , List-Post: List-Help: List-Subscribe: , Cc: Andrew Cooper , Wei Liu , Jan Beulich , =?utf-8?q?Roger_Pau_Monn=C3=A9?= Errors-To: xen-devel-bounces@lists.xenproject.org Sender: "Xen-devel" Rewrite the size checks in a way which which doesn't depend on Xen being compiled as 64bit. Introduce a check missing from the old code, that total_size is a multiple of 1024 bytes, and drop unnecessarily defines/macros/structures. No practical change in behaviour. Signed-off-by: Andrew Cooper --- CC: Jan Beulich CC: Wei Liu CC: Roger Pau Monné --- xen/arch/x86/cpu/microcode/intel.c | 147 +++++++++++++++---------------------- 1 file changed, 58 insertions(+), 89 deletions(-) diff --git a/xen/arch/x86/cpu/microcode/intel.c b/xen/arch/x86/cpu/microcode/intel.c index bc3bbf139e..2cccf9c26d 100644 --- a/xen/arch/x86/cpu/microcode/intel.c +++ b/xen/arch/x86/cpu/microcode/intel.c @@ -65,17 +65,15 @@ struct microcode_intel { }; /* microcode format is extended from prescott processors */ -struct extended_signature { - unsigned int sig; - unsigned int pf; - unsigned int cksum; -}; - struct extended_sigtable { unsigned int count; unsigned int cksum; unsigned int reserved[3]; - struct extended_signature sigs[0]; + struct { + unsigned int sig; + unsigned int pf; + unsigned int cksum; + } sigs[]; }; struct microcode_patch { @@ -84,9 +82,6 @@ struct microcode_patch { #define PPRO_UCODE_DATASIZE 2000 #define MC_HEADER_SIZE (sizeof(struct microcode_header_intel)) -#define EXT_HEADER_SIZE (sizeof(struct extended_sigtable)) -#define EXT_SIGNATURE_SIZE (sizeof(struct extended_signature)) -#define DWSIZE (sizeof(u32)) static uint32_t get_datasize(const struct microcode_header_intel *hdr) { @@ -134,8 +129,6 @@ static bool signature_maches(const struct cpu_signature *cpu_sig, return cpu_sig->pf & ucode_pf; } -#define exttable_size(et) ((et)->count * EXT_SIGNATURE_SIZE + EXT_HEADER_SIZE) - static int collect_cpu_info(struct cpu_signature *csig) { uint64_t msr_content; @@ -160,93 +153,69 @@ static int collect_cpu_info(struct cpu_signature *csig) return 0; } +/* + * Sanity check a blob which is expected to be a microcode patch. The 48 byte + * header is of a known format, and together with totalsize are within the + * bounds of the container. Everything else is unchecked. + */ static int microcode_sanity_check(const struct microcode_intel *mc) { - const struct microcode_header_intel *mc_header = &mc->hdr; - const struct extended_sigtable *ext_header = NULL; - const struct extended_signature *ext_sig; - unsigned long total_size, data_size, ext_table_size; - unsigned int ext_sigcount = 0, i; - uint32_t sum, orig_sum; - - total_size = get_totalsize(mc_header); - data_size = get_datasize(mc_header); - if ( (data_size + MC_HEADER_SIZE) > total_size ) - { - printk(KERN_ERR "microcode: error! " - "Bad data size in microcode data file\n"); + const struct extended_sigtable *ext; + unsigned int total_size = get_totalsize(&mc->hdr); + unsigned int data_size = get_datasize(&mc->hdr); + unsigned int i, ext_size; + uint32_t sum, *ptr; + + /* + * Total size must be a multiple of 1024 bytes. Data size and the header + * must fit within it. + */ + if ( (total_size & 1023) || + data_size > (total_size - MC_HEADER_SIZE) ) return -EINVAL; - } - if ( (mc_header->ldrver != 1) || (mc_header->hdrver != 1) ) - { - printk(KERN_ERR "microcode: error! " - "Unknown microcode update format\n"); + /* Checksum the main header and data. */ + for ( sum = 0, ptr = (uint32_t *)mc; + ptr < (uint32_t *)&mc->data[data_size]; ++ptr ) + sum += *ptr; + + if ( sum != 0 ) return -EINVAL; - } - ext_table_size = total_size - (MC_HEADER_SIZE + data_size); - if ( ext_table_size ) - { - if ( (ext_table_size < EXT_HEADER_SIZE) || - ((ext_table_size - EXT_HEADER_SIZE) % EXT_SIGNATURE_SIZE) ) - { - printk(KERN_ERR "microcode: error! " - "Small exttable size in microcode data file\n"); - return -EINVAL; - } - ext_header = (void *)mc + MC_HEADER_SIZE + data_size; - if ( ext_table_size != exttable_size(ext_header) ) - { - printk(KERN_ERR "microcode: error! " - "Bad exttable size in microcode data file\n"); - return -EFAULT; - } - ext_sigcount = ext_header->count; - } - /* check extended table checksum */ - if ( ext_table_size ) - { - uint32_t ext_table_sum = 0; - uint32_t *ext_tablep = (uint32_t *)ext_header; + /* Look to see if there is an extended signature table. */ + ext_size = total_size - data_size - MC_HEADER_SIZE; - i = ext_table_size / DWSIZE; - while ( i-- ) - ext_table_sum += ext_tablep[i]; - if ( ext_table_sum ) - { - printk(KERN_WARNING "microcode: aborting, " - "bad extended signature table checksum\n"); - return -EINVAL; - } - } + /* No extended signature table? All done. */ + if ( ext_size == 0 ) + return 0; - /* calculate the checksum */ - orig_sum = 0; - i = (MC_HEADER_SIZE + data_size) / DWSIZE; - while ( i-- ) - orig_sum += ((uint32_t *)mc)[i]; - if ( orig_sum ) - { - printk(KERN_ERR "microcode: aborting, bad checksum\n"); + /* + * Check the structure of the extended signature table, ensuring that it + * fits exactly in the remaining space. + */ + ext = (void *)&mc->data[data_size]; + if ( ext_size < sizeof(*ext) || + (ext_size - sizeof(*ext)) % sizeof(ext->sigs[0]) || + (ext_size - sizeof(*ext)) / sizeof(ext->sigs[0]) != ext->count ) return -EINVAL; - } - if ( !ext_table_size ) - return 0; - /* check extended signature checksum */ - for ( i = 0; i < ext_sigcount; i++ ) - { - ext_sig = (void *)ext_header + EXT_HEADER_SIZE + - EXT_SIGNATURE_SIZE * i; - sum = orig_sum - - (mc_header->sig + mc_header->pf + mc_header->cksum) - + (ext_sig->sig + ext_sig->pf + ext_sig->cksum); - if ( sum ) - { - printk(KERN_ERR "microcode: aborting, bad checksum\n"); + + /* Checksum the whole extended signature table. */ + for ( sum = 0, ptr = (uint32_t *)ext; + ptr < (uint32_t *)&ext->sigs[ext->count]; ++ptr ) + sum += *ptr; + + if ( sum != 0 ) + return -EINVAL; + + /* + * Checksum each indiviudal extended signature as if it had been in the + * main header. + */ + sum = mc->hdr.sig + mc->hdr.pf + mc->hdr.cksum; + for ( i = 0; i < ext->count; ++i ) + if ( sum != (ext->sigs[i].sig + ext->sigs[i].pf + ext->sigs[i].cksum) ) return -EINVAL; - } - } + return 0; }