From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1755348AbbINMZZ (ORCPT ); Mon, 14 Sep 2015 08:25:25 -0400 Received: from terminus.zytor.com ([198.137.202.10]:35327 "EHLO terminus.zytor.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751042AbbINMZV (ORCPT ); Mon, 14 Sep 2015 08:25:21 -0400 Date: Mon, 14 Sep 2015 05:24:19 -0700 From: tip-bot for Dave Hansen Message-ID: Cc: brgerst@gmail.com, dvlasenk@redhat.com, torvalds@linux-foundation.org, peterz@infradead.org, mingo@kernel.org, tglx@linutronix.de, luto@amacapital.net, tim.c.chen@linux.intel.com, dave.hansen@linux.intel.com, fenghua.yu@intel.com, bp@alien8.de, linux-kernel@vger.kernel.org, hpa@zytor.com Reply-To: brgerst@gmail.com, dvlasenk@redhat.com, torvalds@linux-foundation.org, mingo@kernel.org, peterz@infradead.org, tglx@linutronix.de, tim.c.chen@linux.intel.com, luto@amacapital.net, fenghua.yu@intel.com, dave.hansen@linux.intel.com, bp@alien8.de, hpa@zytor.com, linux-kernel@vger.kernel.org In-Reply-To: <20150902233130.0843AB15@viggo.jf.intel.com> References: <20150902233130.0843AB15@viggo.jf.intel.com> To: linux-tip-commits@vger.kernel.org Subject: [tip:x86/fpu] x86/fpu: Check to ensure increasing-offset xstate offsets Git-Commit-ID: e6e888f96b4a531886f3bf29ba9af0b6f1026365 X-Mailer: tip-git-log-daemon Robot-ID: Robot-Unsubscribe: Contact to get blacklisted from these emails MIME-Version: 1.0 Content-Transfer-Encoding: 8bit Content-Type: text/plain; charset=UTF-8 Content-Disposition: inline Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Commit-ID: e6e888f96b4a531886f3bf29ba9af0b6f1026365 Gitweb: http://git.kernel.org/tip/e6e888f96b4a531886f3bf29ba9af0b6f1026365 Author: Dave Hansen AuthorDate: Wed, 2 Sep 2015 16:31:30 -0700 Committer: Ingo Molnar CommitDate: Mon, 14 Sep 2015 12:22:02 +0200 x86/fpu: Check to ensure increasing-offset xstate offsets The xstate CPUID leaves enumerate where each state component is inside the XSAVE buffer, along with the size of the entire buffer. Our new XSAVE sanity-checking code extrapolates an expected _total_ buffer size by looking at the last component that it encounters. That method requires that the highest-numbered component also be the one with the highest offset. This is a pretty safe assumption, but let's add some code to ensure it stays true. To make this check work correctly, we also need to ensure we only consider the offsets from enabled features because the offset register (ebx) will return 0 on unsupported features. This also means that we will preserve the -1's that we initialized xstate_offsets/sizes[] with. That will help find bugs. Signed-off-by: Dave Hansen Cc: Andy Lutomirski Cc: Borislav Petkov Cc: Brian Gerst Cc: Denys Vlasenko Cc: Fenghua Yu Cc: H. Peter Anvin Cc: Linus Torvalds Cc: Peter Zijlstra Cc: Thomas Gleixner Cc: Tim Chen Cc: dave@sr71.net Cc: linux-kernel@vger.kernel.org Link: http://lkml.kernel.org/r/20150902233130.0843AB15@viggo.jf.intel.com Signed-off-by: Ingo Molnar --- arch/x86/kernel/fpu/xstate.c | 35 ++++++++++++++++++++++++----------- 1 file changed, 24 insertions(+), 11 deletions(-) diff --git a/arch/x86/kernel/fpu/xstate.c b/arch/x86/kernel/fpu/xstate.c index 4704955..a8297f2 100644 --- a/arch/x86/kernel/fpu/xstate.c +++ b/arch/x86/kernel/fpu/xstate.c @@ -185,18 +185,41 @@ void fpu__init_cpu_xstate(void) } /* + * Note that in the future we will likely need a pair of + * functions here: one for user xstates and the other for + * system xstates. For now, they are the same. + */ +static int xfeature_enabled(enum xfeature xfeature) +{ + return !!(xfeatures_mask & (1UL << xfeature)); +} + +/* * Record the offsets and sizes of various xstates contained * in the XSAVE state memory layout. */ static void __init setup_xstate_features(void) { u32 eax, ebx, ecx, edx, i; + /* start at the beginnning of the "extended state" */ + unsigned int last_good_offset = offsetof(struct xregs_state, + extended_state_area); for (i = FIRST_EXTENDED_XFEATURE; i < XFEATURE_MAX; i++) { - cpuid_count(XSTATE_CPUID, i, &eax, &ebx, &ecx, &edx); + if (!xfeature_enabled(i)) + continue; + cpuid_count(XSTATE_CPUID, i, &eax, &ebx, &ecx, &edx); xstate_offsets[i] = ebx; xstate_sizes[i] = eax; + /* + * In our xstate size checks, we assume that the + * highest-numbered xstate feature has the + * highest offset in the buffer. Ensure it does. + */ + WARN_ONCE(last_good_offset > xstate_offsets[i], + "x86/fpu: misordered xstate at %d\n", last_good_offset); + last_good_offset = xstate_offsets[i]; printk(KERN_INFO "x86/fpu: xstate_offset[%d]: %4d, xstate_sizes[%d]: %4d\n", i, ebx, i, eax); } @@ -226,16 +249,6 @@ static void __init print_xstate_features(void) } /* - * Note that in the future we will likely need a pair of - * functions here: one for user xstates and the other for - * system xstates. For now, they are the same. - */ -static int xfeature_enabled(enum xfeature xfeature) -{ - return !!(xfeatures_mask & (1UL << xfeature)); -} - -/* * This function sets up offsets and sizes of all extended states in * xsave area. This supports both standard format and compacted format * of the xsave aread.