|
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] Re: [PATCH 09/16] x86/cpu: Adjust enable_nmis() to be shadow stack compatible
On 02.05.2020 00:58, Andrew Cooper wrote:
> When executing an IRET-to-self, the shadow stack must agree with the regular
> stack. We can't manipulate SSP directly, so have to fake a shadow IRET frame
> by executing 3 CALLs, then editing the result to look correct.
>
> This is not a fastpath, is called on the BSP long before CET can be set up,
> and may be called on the crash path after CET is disabled. Use the fact that
> INCSSP is allocated from the hint nop space to construct a test for CET being
> active which is safe on all processors.
>
> Signed-off-by: Andrew Cooper <andrew.cooper3@xxxxxxxxxx>
Reviewed-by: Jan Beulich <jbeulich@xxxxxxxx>
albeit with a question which may make a further change necessary:
> --- a/xen/include/asm-x86/processor.h
> +++ b/xen/include/asm-x86/processor.h
> @@ -544,17 +544,40 @@ static inline void enable_nmis(void)
> {
> unsigned long tmp;
>
> - asm volatile ( "mov %%rsp, %[tmp] \n\t"
> - "push %[ss] \n\t"
> - "push %[tmp] \n\t"
> - "pushf \n\t"
> - "push %[cs] \n\t"
> - "lea 1f(%%rip), %[tmp] \n\t"
> - "push %[tmp] \n\t"
> - "iretq; 1: \n\t"
> - : [tmp] "=&r" (tmp)
> + asm volatile ( "mov %%rsp, %[rsp] \n\t"
> + "lea .Ldone(%%rip), %[rip] \n\t"
> +#ifdef CONFIG_XEN_SHSTK
> + /* Check for CET-SS being active. */
> + "mov $1, %k[ssp] \n\t"
> + "rdsspq %[ssp] \n\t"
> + "cmp $1, %k[ssp] \n\t"
> + "je .Lshstk_done \n\t"
> +
> + /* Push 3 words on the shadow stack */
> + ".rept 3 \n\t"
> + "call 1f; nop; 1: \n\t"
> + ".endr \n\t"
> +
> + /* Fixup to be an IRET shadow stack frame */
> + "wrssq %q[cs], -1*8(%[ssp]) \n\t"
> + "wrssq %[rip], -2*8(%[ssp]) \n\t"
> + "wrssq %[ssp], -3*8(%[ssp]) \n\t"
> +
> + ".Lshstk_done:"
> +#endif
> + /* Write an IRET regular frame */
> + "push %[ss] \n\t"
> + "push %[rsp] \n\t"
> + "pushf \n\t"
> + "push %q[cs] \n\t"
> + "push %[rip] \n\t"
> + "iretq \n\t"
> + ".Ldone: \n\t"
> + : [rip] "=&r" (tmp),
> + [rsp] "=&r" (tmp),
> + [ssp] "=&r" (tmp)
Even after an hour of reading and searching through the gcc docs
I can't convince myself that this utilizes defined behavior. We
do tie multiple outputs to the same C variable elsewhere, yes,
but only in cases where we don't really care about the register,
or where the register is a fixed one anyway. What I can't find
is a clear statement that gcc wouldn't ever, now or in the
future, use the same register for all three outputs. I think one
can deduce this in certain ways, and experimentation also seems
to confirm it, but still.
Jan
|
![]() |
Lists.xenproject.org is hosted with RackSpace, monitoring our |