|
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] Re: [PATCH v2 10/14] x86/extable: Adjust extable handling to be shadow stack compatible
On 28/05/2020 17:15, Jan Beulich wrote:
> On 27.05.2020 21:18, Andrew Cooper wrote:
>> @@ -400,6 +400,18 @@ unsigned long get_stack_trace_bottom(unsigned long sp)
>> }
>> }
>>
>> +static unsigned long get_shstk_bottom(unsigned long sp)
>> +{
>> + switch ( get_stack_page(sp) )
>> + {
>> +#ifdef CONFIG_XEN_SHSTK
>> + case 0: return ROUNDUP(sp, IST_SHSTK_SIZE) - sizeof(unsigned long);
>> + case 5: return ROUNDUP(sp, PAGE_SIZE) - sizeof(unsigned long);
> PRIMARY_SHSTK_SLOT please and, if introduced as suggested for the
> earlier patch, IST_SHSTK_SLOT in the earlier line.
>
>> @@ -763,6 +775,56 @@ static void do_reserved_trap(struct cpu_user_regs *regs)
>> trapnr, vec_name(trapnr), regs->error_code);
>> }
>>
>> +static void extable_shstk_fixup(struct cpu_user_regs *regs, unsigned long
>> fixup)
>> +{
>> + unsigned long ssp, *ptr, *base;
>> +
>> + asm ( "rdsspq %0" : "=r" (ssp) : "0" (1) );
>> + if ( ssp == 1 )
>> + return;
>> +
>> + ptr = _p(ssp);
>> + base = _p(get_shstk_bottom(ssp));
>> +
>> + for ( ; ptr < base; ++ptr )
>> + {
>> + /*
>> + * Search for %rip. The shstk currently looks like this:
>> + *
>> + * ... [Likely pointed to by SSP]
>> + * %cs [== regs->cs]
>> + * %rip [== regs->rip]
>> + * SSP [Likely points to 3 slots higher, above %cs]
>> + * ... [call tree to this function, likely 2/3 slots]
>> + *
>> + * and we want to overwrite %rip with fixup. There are two
>> + * complications:
>> + * 1) We cant depend on SSP values, because they won't differ by 3
>> + * slots if the exception is taken on an IST stack.
>> + * 2) There are synthetic (unrealistic but not impossible)
>> scenarios
>> + * where %rip can end up in the call tree to this function, so
>> we
>> + * can't check against regs->rip alone.
>> + *
>> + * Check for both reg->rip and regs->cs matching.
> Nit: regs->rip
>
>> + */
>> +
>> + if ( ptr[0] == regs->rip && ptr[1] == regs->cs )
>> + {
>> + asm ( "wrssq %[fix], %[stk]"
>> + : [stk] "=m" (*ptr)
> Could this be ptr[0], to match the if()?
>
> Considering how important it is that we don't fix up the wrong stack
> location here, I continue to wonder if we wouldn't better also
> include the SSP value on the stack in the checking, at the very
> least by way of an ASSERT() or BUG_ON().
Well no, for the reason discussed in point 1.
Its not technically an issue right now, but there is no possible way to
BUILD_BUG_ON() someone turning an exception into IST, or stopping the
use of the extable infrastructure on a #DB.
Such a check would lie in wait and either provide an unexpected tangent
to someone debugging a complicated issue (I do use #DB for a fair bit),
or become a security vulnerability.
> Since, with how the code is
> currently written, this would require a somewhat odd looking ptr[-1]
> I also wonder whether "while ( ++ptr < base )" as the loop header
> wouldn't be better. The first entry on the stack can't be the RIP
> we look for anyway, can it?
Yes it can.
>> --- a/xen/arch/x86/x86_64/entry.S
>> +++ b/xen/arch/x86/x86_64/entry.S
>> @@ -708,7 +708,16 @@ exception_with_ints_disabled:
>> call search_pre_exception_table
>> testq %rax,%rax # no fixup code for faulting EIP?
>> jz 1b
>> - movq %rax,UREGS_rip(%rsp)
>> + movq %rax,UREGS_rip(%rsp) # fixup regular stack
>> +
>> +#ifdef CONFIG_XEN_SHSTK
>> + mov $1, %edi
>> + rdsspq %rdi
>> + cmp $1, %edi
>> + je .L_exn_shstk_done
>> + wrssq %rax, (%rdi) # fixup shadow stack
> According to the comment in extable_shstk_fixup(), isn't the value
> to be replaced at 8(%rdi)?
Hmm - I think you're right. I thought I had this covered by unit tests.
~Andrew
|
![]() |
Lists.xenproject.org is hosted with RackSpace, monitoring our |