Messages in this thread Patch in this message | | | From | Sai Praneeth Prakhya <> | 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 |
| |
From: Sai Praneeth <sai.praneeth.prakhya@intel.com>
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 <sai.praneeth.prakhya@intel.com> Reported-by: Dave Hansen <dave.hansen@intel.com> Suggested-by: Dave Hansen <dave.hansen@intel.com> Cc: Dave Hansen <dave.hansen@intel.com> Cc: Yu-Cheng Yu <yu-cheng.yu@intel.com> Cc: Fenghua Yu <fenghua.yu@intel.com> Cc: Ravi Shankar <ravi.v.shankar@intel.com> --- 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
| |