Received: by 10.192.245.15 with SMTP id i15csp1108647imn; Sun, 11 Mar 2018 03:01:54 -0700 (PDT) X-Google-Smtp-Source: AG47ELtHCIuAZOKk6ej6VD9TEx8C8rbjMK9B/nrjy+mtuQC0b3dAUV1l2AQrms67srilqiwLcRsd X-Received: by 2002:a17:902:6ecd:: with SMTP id l13-v6mr4465472pln.374.1520762514731; Sun, 11 Mar 2018 03:01:54 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1520762514; cv=none; d=google.com; s=arc-20160816; b=0mTKlb7nd9VGBBuux87m1I87u51n6//NxxIFVxKNCvng6CD9g7CgV3K5U52dunsLrm 0wQn3qvhFoj24W5T1Jj0xKWgJHIX+KwbPIiYzkGD0P5mbv89CoHbhNLu/6yhaxK7Vo9U qAqAM+u7I4N7qwxWWdnihO+YjDqbqv91yvOXkEd+S9eDTKwCfA94BZp3H+2Zy9NnwaUY GGHzcVN0bHr1+JSRt+jHV5BprLexyj705RwJt5x9bG5JuKt8bLbz3LyZ+9klmhxcy/sW P5chdM9OKLLOcPJCuiYW1JFun9hkGq4zAmzpeIbyRNMSYr8lVNDLQr6443WxTS2Meeig O4vg== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:user-agent:in-reply-to :content-disposition:mime-version:references:message-id:subject:cc :to:from:date:dkim-signature:arc-authentication-results; bh=wachJjtFOkoh/9GkYxRgYKTCgpibuFrIriFnBRWAOeA=; b=TlFFSCJVoxyQ0+PvDYlPJvX+3bgDQqs0WJ0Bl0pD7GKQpOXwScXKm3Y7iuoPaJK/3j 0N70mF54keFBPILZJCAw1mvi2OwmCJMzMyIMAKIjKeGUC0+c91ocRKwwgZf5uO21sp+H aILSx+y20VbFRrNDnIk5WJDIXoklsN4sJOwc258FT/uaoAGCmoXaAopPRrBGnecXyUUl Cp5r2f7zs1qwdO1nSn+Wl/LyMzx1gRuHFX0SJ0J0BjuNhsHlb4kPHtIGHrsIWzxz9KT6 KOfuvR/t/6QFmuEh98DQftASGIZpIyiJk643ngWpKpT4E+4u5sffxzM7LCLlUaq+je/G Eaxw== ARC-Authentication-Results: i=1; mx.google.com; dkim=fail header.i=@gmail.com header.s=20161025 header.b=Rko5xloP; 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 v196si3470839pgb.217.2018.03.11.03.01.26; Sun, 11 Mar 2018 03:01:54 -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; dkim=fail header.i=@gmail.com header.s=20161025 header.b=Rko5xloP; 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 S932136AbeCKJ76 (ORCPT + 99 others); Sun, 11 Mar 2018 05:59:58 -0400 Received: from mail-wm0-f67.google.com ([74.125.82.67]:51592 "EHLO mail-wm0-f67.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S932113AbeCKJ74 (ORCPT ); Sun, 11 Mar 2018 05:59:56 -0400 Received: by mail-wm0-f67.google.com with SMTP id h21so11062289wmd.1 for ; Sun, 11 Mar 2018 01:59:55 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=sender:date:from:to:cc:subject:message-id:references:mime-version :content-disposition:in-reply-to:user-agent; bh=wachJjtFOkoh/9GkYxRgYKTCgpibuFrIriFnBRWAOeA=; b=Rko5xloPb+yh/KVLhR+5EX7vo0DUVm+wskrUehOV6YfwnnT9ne+aWDGWZNBkaCzOpt wPCIK9FReHoznWRjdBcBpkjA9eMCy98Z7ZKr45e+gP1cOq9N5ceVz4dg1w4Ha9hYzgB3 OfBS7d/n0f0LI3iLoGUaqifhLFeHGyalsjdu0pXS9VpffYI7bBwXmIai9bp5niY0c7Vx IwvM10ArSnAr14p0WyS8RDAOf/FB3Gt6pVpPWbwgxYP7bruodWAJumKqfMaU+pNKU50K djbvbrWZRzUbEly7G8w6NbrRSugEVD1u4HZ9lnUeJdpUuJ1NYfrJdJx8cU94LwuDOjYj H/zQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:sender:date:from:to:cc:subject:message-id :references:mime-version:content-disposition:in-reply-to:user-agent; bh=wachJjtFOkoh/9GkYxRgYKTCgpibuFrIriFnBRWAOeA=; b=Ckilyc5CaaDcaFapmO0qmSOxfHAgRaG/g3dnxxGvOx+ImiAVP3sEp98WuiV8fzZ5Of 10+CnOLDUk5djZ37k6Ll9825O1j+feJdWD+xNWUTlLStalitAahsvK9+bL+jzAPDKOXx cShvL4rbrzESvdHNvyy0XESRoK+rDw8FGw0ALOBjUtgo94PQFClwml3h7INdvO+ds9+B r5m92SPIK/Gh8/Cfy+F1qO3bZjf2gigsCN/UISlrwb/YJzpyKW2H/++LBPvN8ayjfjh1 S3DCr0OaMcnZNUee0Fg3Zp6zqQHfuDrDiPcUcq2bnI4/2iQnH7pRopqyjiirwpS0qgAK OIiA== X-Gm-Message-State: AElRT7G3FDyfPJBGrQGOqHb+u2LieiGvhp/WN+L28hpIe1F6K712ejFr bpvKdN4cmgtlAXLIICASY00= X-Received: by 10.28.169.67 with SMTP id s64mr2754849wme.37.1520762395005; Sun, 11 Mar 2018 01:59:55 -0800 (PST) Received: from gmail.com (2E8B0CD5.catv.pool.telekom.hu. [46.139.12.213]) by smtp.gmail.com with ESMTPSA id p79sm1390179wmf.34.2018.03.11.01.59.53 (version=TLS1_2 cipher=ECDHE-RSA-CHACHA20-POLY1305 bits=256/256); Sun, 11 Mar 2018 01:59:54 -0800 (PST) Date: Sun, 11 Mar 2018 10:59:52 +0100 From: Ingo Molnar To: "Maciej S. Szmigiero" Cc: Borislav Petkov , Thomas Gleixner , Ingo Molnar , "H. Peter Anvin" , x86@kernel.org, linux-kernel@vger.kernel.org Subject: Re: [PATCH] x86/microcode/AMD: check microcode file sanity before loading it Message-ID: <20180311095952.vphoszyohug7tkme@gmail.com> References: <34e9d679-2eca-90cf-9a95-3864f0be060e@maciej.szmigiero.name> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: <34e9d679-2eca-90cf-9a95-3864f0be060e@maciej.szmigiero.name> User-Agent: NeoMutt/20170609 (1.8.3) Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org * Maciej S. Szmigiero wrote: > Currently, it is very easy to make the AMD microcode update driver crash > or spin on a malformed microcode file since it does very little > consistency checking on data loaded from such file. > > This commit introduces various checks, mostly on length-type fields, so > all corrupted microcode files are (hopefully) correctly rejected instead. > > Signed-off-by: Maciej S. Szmigiero > --- > Test files are at https://pastebin.com/XkKUSmMp > One has to enable KASAN in the kernel config and rename a particular > test file to name appropriate to the running CPU family to test its > loading. > > arch/x86/include/asm/microcode_amd.h | 6 ++ > arch/x86/kernel/cpu/microcode/amd.c | 111 ++++++++++++++++++++++++++--------- > 2 files changed, 89 insertions(+), 28 deletions(-) Treating microcode update files as external input and sanity checking the data makes sense I suppose, but there's various small uglies in the patch: > +/* if a patch is larger than this the microcode file is surely corrupted */ > +#define PATCH_MAX_SIZE_ABSOLUTE (16 * 1024 * 1024) Please capitalize comments. > * Returns the amount of bytes consumed while scanning. @desc contains all the > * data we're going to use in later stages of the application. > */ > -static ssize_t parse_container(u8 *ucode, ssize_t size, struct cont_desc *desc) > +static size_t parse_container(u8 *ucode, size_t size, struct cont_desc *desc) > { > struct equiv_cpu_entry *eq; > - ssize_t orig_size = size; > + size_t orig_size = size; > u32 *hdr = (u32 *)ucode; > + u32 eqsize; > u16 eq_id; > u8 *buf; So we have 'eq_id', but 'eqsize'? Why not 'eq_size' to have fewer random variations of coding style? > > + if (size < CONTAINER_HDR_SZ) > + return 0; The comment about CONTAINER_HDR_SZ better belongs here, where we use it. > /* Am I looking at an equivalence table header? */ > if (hdr[0] != UCODE_MAGIC || > hdr[1] != UCODE_EQUIV_CPU_TABLE_TYPE || > hdr[2] == 0) > return CONTAINER_HDR_SZ; > > + eqsize = hdr[2]; > + if (eqsize < sizeof(*eq) || > + eqsize > UCODE_EQUIV_CPU_TABLE_MAX_SIZE) > + return 0; > + > + if (size < CONTAINER_HDR_SZ + eqsize) > + return 0; > + > buf = ucode; > > 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, eqsize / sizeof(*eq), desc->cpuid_1_eax); Does eq_size have to be a multiple of sizeof(*eq)? If yes then we should probably check that too. > -static int install_equiv_cpu_table(const u8 *buf) > +static int install_equiv_cpu_table(const u8 *buf, size_t bufsize) s/bufsize/buf_size > { > unsigned int *ibuf = (unsigned int *)buf; > - unsigned int type = ibuf[1]; > - unsigned int size = ibuf[2]; > + unsigned int type, size; > > - if (type != UCODE_EQUIV_CPU_TABLE_TYPE || !size) { > - pr_err("empty section/" > - "invalid type field in container file section header\n"); > + if (bufsize < CONTAINER_HDR_SZ) { > + pr_err("no container header\n"); > + return -EINVAL; > + } > + > + type = ibuf[1]; > + if (type != UCODE_EQUIV_CPU_TABLE_TYPE) { > + pr_err("invalid type field in container file section header\n"); > + return -EINVAL; > + } > + > + size = ibuf[2]; > + if (size < sizeof(struct equiv_cpu_entry) || > + size > UCODE_EQUIV_CPU_TABLE_MAX_SIZE) { > + pr_err("equivalent CPU table size invalid\n"); > + return -EINVAL; > + } > + > + if (bufsize < CONTAINER_HDR_SZ + size) { > + pr_err("equivalent CPU table truncated\n"); > return -EINVAL; > } > > @@ -559,6 +599,7 @@ static int install_equiv_cpu_table(const u8 *buf) > } > > memcpy(equiv_cpu_table, buf + CONTAINER_HDR_SZ, size); > + equiv_cpu_table_size = size / sizeof(struct equiv_cpu_entry); Btw., 'equiv_cpu_table_size' is an ambiguous name: often _size variables are in byte units - but this is number of entries. So the name should be 'equiv_cpu_table_entries' or so. Thanks, Ingo