Messages in this thread Patch in this message | | | From | "Chang S. Bae" <> | Subject | [PATCH v11 18/29] x86/fpu/xstate: Disable XSTATE support if an inconsistent state is detected | Date | Fri, 1 Oct 2021 15:37:17 -0700 |
| |
The kernel has a sanity check between two methods to calculate XSTATE size. In the unlikely event that they disagree, disable the use of XSTATE.
Suggested-by: Thomas Gleixner <tglx@linutronix.de> Signed-off-by: Chang S. Bae <chang.seok.bae@intel.com> Reviewed-by: Len Brown <len.brown@intel.com> Cc: x86@kernel.org Cc: linux-kernel@vger.kernel.org --- Changes from v4: * Added as a new patch. (Thomas Gleixner) --- arch/x86/kernel/fpu/xstate.c | 40 ++++++++++++++++++++++++------------ 1 file changed, 27 insertions(+), 13 deletions(-)
diff --git a/arch/x86/kernel/fpu/xstate.c b/arch/x86/kernel/fpu/xstate.c index b6bf32cb650d..e5a734d88660 100644 --- a/arch/x86/kernel/fpu/xstate.c +++ b/arch/x86/kernel/fpu/xstate.c @@ -608,11 +608,11 @@ static void __xstate_dump_leaves(void) } while (0) #define XCHECK_SZ(sz, nr, nr_macro, __struct) do { \ - if ((nr == nr_macro) && \ - WARN_ONCE(sz != sizeof(__struct), \ - "%s: struct is %zu bytes, cpu state %d bytes\n", \ - __stringify(nr_macro), sizeof(__struct), sz)) { \ + if ((nr == nr_macro) && (sz != sizeof(__struct))) { \ + pr_err("%s: struct is %zu bytes, cpu state %d bytes\n", \ + __stringify(nr_macro), sizeof(__struct), sz); \ __xstate_dump_leaves(); \ + return -EINVAL; \ } \ } while (0) @@ -621,7 +621,7 @@ static void __xstate_dump_leaves(void) * that our software representation matches what the CPU * tells us about the state's size. */ -static void check_xstate_against_struct(int nr) +static int check_xstate_against_struct(int nr) { /* * Ask the CPU for the size of the state. @@ -649,9 +649,12 @@ static void check_xstate_against_struct(int nr) (nr >= XFEATURE_MAX) || (nr == XFEATURE_PT_UNIMPLEMENTED_SO_FAR) || ((nr >= XFEATURE_RSRVD_COMP_11) && (nr <= XFEATURE_LBR))) { - WARN_ONCE(1, "no structure for xstate: %d\n", nr); + pr_err("no structure for xstate: %d\n", nr); XSTATE_WARN_ON(1); + return -EINVAL; } + + return 0; } /** @@ -664,13 +667,14 @@ static void check_xstate_against_struct(int nr) * excluded. Only the size of the buffer for task->fpu is checked here. * * @include_dynamic_states: A knob to include dynamic states or not. + * @size: A pointer to record the size. * - * Return: The calculated xstate size. + * Return: 0 if successful; otherwise, error code. */ -static unsigned int calculate_xstate_size(bool include_dynamic_states) +static int calculate_xstate_size(bool include_dynamic_states, unsigned int *size) { unsigned int xstate_size = FXSAVE_SIZE + XSAVE_HDR_SIZE; - int i; + int i, err; for (i = FIRST_EXTENDED_XFEATURE; i < XFEATURE_MAX; i++) { if (!xfeature_enabled(i)) @@ -679,7 +683,10 @@ static unsigned int calculate_xstate_size(bool include_dynamic_states) if ((xfeatures_mask_user_dynamic & BIT_ULL(i)) && !include_dynamic_states) continue; - check_xstate_against_struct(i); + err = check_xstate_against_struct(i); + if (err) + return err; + /* * Supervisor state components can be managed only by * XSAVES. @@ -705,7 +712,9 @@ static unsigned int calculate_xstate_size(bool include_dynamic_states) xstate_size += xfeature_size(i); } - return xstate_size; + if (size) + *size = xstate_size; + return 0; } /* @@ -791,6 +800,7 @@ static int __init init_xstate_size(void) /* Recompute the context size for enabled features: */ unsigned int possible_xstate_size, xstate_size; unsigned int xsave_size; + int err; xsave_size = get_xsave_size(); @@ -803,14 +813,18 @@ static int __init init_xstate_size(void) * Calculate the maximum xstate size, including the dynamic states. */ fpu_buf_cfg.max_size = possible_xstate_size; - xstate_size = calculate_xstate_size(true); + err = calculate_xstate_size(true, &xstate_size); + if (err) + return err; XSTATE_WARN_ON(possible_xstate_size != xstate_size); /* * Calculate the minimum xstate size, i.e., excluding the dynamic * xstates. */ - xstate_size = calculate_xstate_size(false); + err = calculate_xstate_size(false, &xstate_size); + if (err) + return err; if (!is_supported_xstate_size(xstate_size)) return -EINVAL; -- 2.17.1
| |