From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1753953AbcGYVJ0 (ORCPT ); Mon, 25 Jul 2016 17:09:26 -0400 Received: from mga09.intel.com ([134.134.136.24]:21562 "EHLO mga09.intel.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1753073AbcGYVJW (ORCPT ); Mon, 25 Jul 2016 17:09:22 -0400 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.28,421,1464678000"; d="scan'208";a="739627478" From: Sai Praneeth Prakhya To: x86@kernel.org, linux-kernel@vger.kernel.org Cc: Sai Praneeth , Dave Hansen , Yu-Cheng Yu , Fenghua Yu , Ravi Shankar Subject: [PATCH] x86/fpu/xstate: Return error if xfeature bit is unset in XSAVES compacted-format buffer Date: Mon, 25 Jul 2016 14:08:08 -0700 Message-Id: <1469480888-14363-1-git-send-email-sai.praneeth.prakhya@intel.com> X-Mailer: git-send-email 2.1.4 Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org From: Sai Praneeth Currently, XSAVES compacted-format buffer will always contain space for all enabled states. If XSAVES compacted-format buffer is in use and an xstate component (E.g: PKRU xstate) is not present in the buffer (i.e. xcomp_bv does not have xfeature (E.g: XFEATURE_MASK_PKRU) bit set), then fpu__xfeature_set_state() returns error. Signed-off-by: Sai Praneeth Prakhya Reported-by: Dave Hansen Suggested-by: Dave Hansen Cc: Dave Hansen Cc: Yu-Cheng Yu Cc: Fenghua Yu Cc: Ravi Shankar --- arch/x86/kernel/fpu/xstate.c | 27 +++++++++++++++------------ 1 file changed, 15 insertions(+), 12 deletions(-) diff --git a/arch/x86/kernel/fpu/xstate.c b/arch/x86/kernel/fpu/xstate.c index 680049aa4593..bc97aa2832c6 100644 --- a/arch/x86/kernel/fpu/xstate.c +++ b/arch/x86/kernel/fpu/xstate.c @@ -893,7 +893,7 @@ static void fpu__xfeature_set_non_init(struct xregs_state *xsave, * address of the state in the xsave area or NULL if the state * is not present or is in its 'init state'. */ -static void fpu__xfeature_set_state(int xstate_feature_mask, +static int fpu__xfeature_set_state(int xstate_feature_mask, void *xstate_feature_src, size_t len) { struct xregs_state *xsave = ¤t->thread.fpu.state.xsave; @@ -902,7 +902,7 @@ static void fpu__xfeature_set_state(int xstate_feature_mask, if (!boot_cpu_has(X86_FEATURE_XSAVE)) { WARN_ONCE(1, "%s() attempted with no xsave support", __func__); - return; + return -ENXIO; } /* @@ -913,14 +913,16 @@ static void fpu__xfeature_set_state(int xstate_feature_mask, fpu__current_fpstate_write_begin(); /* - * This method *WILL* *NOT* work for compact-format - * buffers. If the 'xstate_feature_mask' is unset in - * xcomp_bv then we may need to move other feature state - * "up" in the buffer. + * This method will not work on XSAVES compacted-format buffer + * that do not have space allocated for the state we are trying + * to set. Currently, the kernel always allocates space for all + * enabled states. This check makes sure that holds true. */ - if (xsave->header.xcomp_bv & xstate_feature_mask) { + if (!(xsave->header.xcomp_bv & xstate_feature_mask) &&\ + using_compacted_format()) { WARN_ON_ONCE(1); - goto out; + fpu__current_fpstate_write_end(); + return -EINVAL; } /* find the location in the xsave buffer of the desired state */ @@ -940,12 +942,14 @@ static void fpu__xfeature_set_state(int xstate_feature_mask, * in the buffer now. */ fpu__xfeature_set_non_init(xsave, xstate_feature_mask); -out: + /* * We are done writing to the 'fpu'. Reenable preeption * and (possibly) move the fpstate back in to the fpregs. */ fpu__current_fpstate_write_end(); + + return 0; } #define NR_VALID_PKRU_BITS (CONFIG_NR_PROTECTION_KEYS * 2) @@ -1014,9 +1018,8 @@ int arch_set_user_pkey_access(struct task_struct *tsk, int pkey, */ new_pkru_state.pad = 0; - fpu__xfeature_set_state(XFEATURE_MASK_PKRU, &new_pkru_state, sizeof(new_pkru_state)); - - return 0; + return fpu__xfeature_set_state(XFEATURE_MASK_PKRU, &new_pkru_state, + sizeof(new_pkru_state)); } /* -- 2.1.4