Received: by 10.223.176.46 with SMTP id f43csp1767827wra; Wed, 24 Jan 2018 23:17:46 -0800 (PST) X-Google-Smtp-Source: AH8x227OQv9h47KOSzdsBN0vL6uO6avVMFybOoskfsI4hg/097N5m326pgfJuLwDf3CwTxEr7Xrt X-Received: by 2002:a17:902:1a4:: with SMTP id b33-v6mr10144618plb.58.1516864666712; Wed, 24 Jan 2018 23:17:46 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1516864666; cv=none; d=google.com; s=arc-20160816; b=eo90MjV6ZKrMR5LKdijmba6ZS+AAr76xff/dkIf4LW9sDIe0xjz5CDpeN90oN6mynx 9oDksGrbMiM/uCObRCAX0rX4tcksFop8lTiyRzPxutNWuZp9zmYZErtngnS8/CZCHHs5 1He2sWXC/29SPc+VxHbZ5XvgWMhEsyBD/6CYv8/Q9kkIE6w9WM01HwuTr8vnV7VLlTZa ARtb29/FXBwdCs+Wx5LChmjNLjX1FFWNbG4oII+6tZdTfc5Ln5YgWIRB+S7cgf4BiFNE 8uqAyrazL4iJRc7pnhAmciH/d98TGU9PkcBFXDnZs2C5pE/hiw1afaDFb5FRt101aZ1z Uxeg== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:content-transfer-encoding :content-language:in-reply-to:mime-version:user-agent:date :message-id:from:references:cc:to:subject:arc-authentication-results; bh=jnfLWigF1eZPyH+ouc2f1buH2ziWh7vqYgfWnRZjtY0=; b=lRT3AREQ1KWtwTmIthn7cqx/g0XwNgIKC4Dk6aqqN9Nx0h7lx4KdrkrThvdg5Z/MR1 ZSLrnaByE6Br5oAZMHW1lgZ1Yp3KzFDVQqHgW81ndV7iihd6vz66trsS8TvIhKxJpOh6 8r+wCEwOI+6Xm6Q+8fd22uC/72C33UQ9CblmeyebotoyNmhURYJ9rvXcDEKt019DbB+1 os3yA0mOUYOjnMqxD4SgLLfaFKHsVRkv1rTVmxLl91DFiThN97wpDxCJdmYnLOBrH/i9 S+yjoGRQadU4Oq2OHMHvmyF0bJSxeYkRw17R6TvzpBNyRVezhWLKuk5V9/XkdwK3xmkX QqEg== 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 f19-v6si1510723plj.502.2018.01.24.23.17.21; Wed, 24 Jan 2018 23:17:46 -0800 (PST) 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 S1751244AbeAYHQo (ORCPT + 99 others); Thu, 25 Jan 2018 02:16:44 -0500 Received: from smtp121.ord1c.emailsrvr.com ([108.166.43.121]:39430 "EHLO smtp121.ord1c.emailsrvr.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1750992AbeAYHQl (ORCPT ); Thu, 25 Jan 2018 02:16:41 -0500 Received: from smtp16.relay.ord1c.emailsrvr.com (localhost [127.0.0.1]) by smtp16.relay.ord1c.emailsrvr.com (SMTP Server) with ESMTP id 03609C016B for ; Thu, 25 Jan 2018 02:09:27 -0500 (EST) Received: from smtp73.ord1d.emailsrvr.com (relay.ord1c.rsapps.net [172.28.255.120]) by smtp16.relay.ord1c.emailsrvr.com (SMTP Server) with ESMTPS id F325DC012B for ; Thu, 25 Jan 2018 02:09:26 -0500 (EST) Received: from smtp18.relay.ord1d.emailsrvr.com (localhost [127.0.0.1]) by smtp18.relay.ord1d.emailsrvr.com (SMTP Server) with ESMTP id 54DFBA007F; Thu, 25 Jan 2018 02:09:26 -0500 (EST) X-Auth-ID: cnovikov@lynx.com Received: by smtp18.relay.ord1d.emailsrvr.com (Authenticated sender: cnovikov-AT-lynx.com) with ESMTPSA id 35DFFA0073; Thu, 25 Jan 2018 02:09:25 -0500 (EST) X-Sender-Id: cnovikov@lynx.com Received: from [172.17.80.104] ([TEMPUNAVAIL]. [216.100.252.242]) (using TLSv1.2 with cipher DHE-RSA-AES128-SHA) by 0.0.0.0:465 (trex/5.7.12); Thu, 25 Jan 2018 02:09:26 -0500 Subject: Re: [PATCH v4 02/10] asm/nospec, array_ptr: sanitize speculative array de-references To: Dan Williams , linux-kernel@vger.kernel.org Cc: linux-arch@vger.kernel.org, kernel-hardening@lists.openwall.com, Catalin Marinas , x86@kernel.org, Will Deacon , Russell King , Ingo Molnar , gregkh@linuxfoundation.org, "H. Peter Anvin" , tglx@linutronix.de, torvalds@linux-foundation.org, akpm@linux-foundation.org, alan@linux.intel.com References: <151632009605.21271.11304291057104672116.stgit@dwillia2-desk3.amr.corp.intel.com> <151632010687.21271.12004432287640499992.stgit@dwillia2-desk3.amr.corp.intel.com> From: Cyril Novikov Message-ID: Date: Wed, 24 Jan 2018 23:09:54 -0800 User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64; rv:52.0) Gecko/20100101 Thunderbird/52.5.2 MIME-Version: 1.0 In-Reply-To: <151632010687.21271.12004432287640499992.stgit@dwillia2-desk3.amr.corp.intel.com> Content-Type: text/plain; charset=utf-8; format=flowed Content-Language: en-US Content-Transfer-Encoding: 7bit Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org On 1/18/2018 4:01 PM, Dan Williams wrote: > 'array_ptr' is proposed as a generic mechanism to mitigate against > Spectre-variant-1 attacks, i.e. an attack that bypasses boundary checks > via speculative execution). The 'array_ptr' implementation is expected > to be safe for current generation cpus across multiple architectures > (ARM, x86). I'm an outside reviewer, not subscribed to the list, so forgive me if I do something not according to protocol. I have the following comments on this change: After discarding the speculation barrier variant, is array_ptr() needed at all? You could have a simpler sanitizing macro, say #define array_sanitize_idx(idx, sz) ((idx) & array_ptr_mask((idx), (sz))) (adjusted to not evaluate idx twice). And use it as follows: if (idx < array_size) { idx = array_sanitize_idx(idx, array_size); do_something(array[idx]); } If I understand the speculation stuff correctly, unlike array_ptr(), this "leaks" array[0] rather than nothing (*NULL) when executed speculatively. However, it's still much better than leaking an arbitrary location in memory. The attacker can likely get array[0] "leaked" by passing 0 as idx anyway. > +/* > + * If idx is negative or if idx > size then bit 63 is set in the mask, > + * and the value of ~(-1L) is zero. When the mask is zero, bounds check > + * failed, array_ptr will return NULL. > + */ > +#ifndef array_ptr_mask > +static inline unsigned long array_ptr_mask(unsigned long idx, unsigned long sz) > +{ > + return ~(long)(idx | (sz - 1 - idx)) >> (BITS_PER_LONG - 1); > +} > +#endif Why does this have to resort to the undefined behavior of shifting a negative number to the right? You can do without it: return ((idx | (sz - 1 - idx)) >> (BITS_PER_LONG - 1)) - 1; Of course, you could argue that subtracting 1 from 0 to get all ones is also an undefined behavior, but it's still much better than the shift, isn't it? > +#define array_ptr(base, idx, sz) \ > +({ \ > + union { typeof(*(base)) *_ptr; unsigned long _bit; } __u; \ > + typeof(*(base)) *_arr = (base); \ > + unsigned long _i = (idx); \ > + unsigned long _mask = array_ptr_mask(_i, (sz)); \ > + \ > + __u._ptr = _arr + (_i & _mask); \ > + __u._bit &= _mask; \ > + __u._ptr; \ > +}) Call me paranoid, but I think this may actually create an exploitable bug on 32-bit systems due to casting the index to an unsigned long, if the index as it comes from userland is a 64-bit value. You have *replaced* the "if (idx < array_size)" check with checking if array_ptr() returns NULL. Well, it doesn't return NULL if the low 32 bits of the index are in-bounds, but the high 32 bits are not zero. Apart from the return value pointing to the wrong place, the subsequent code may then assume that the 64-bit idx is actually valid and trip on it badly. -- Cyril