[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 29.05.2020 21:43, Andrew Cooper wrote: > On 28/05/2020 17:15, Jan Beulich wrote: >> On 27.05.2020 21:18, Andrew Cooper wrote: >>> @@ -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. >>> + */ >>> + >>> + 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. I don't see my suggestion in conflict with that point. I didn't suggest an check using == ; instead what I'm thinking about here is something as weak as "Does this point somewhere into the stack range for this CPU?" After all there are only a limited set of classes of entries that can be on a shadow stack: - LIP (Xen .text, livepatching area) - CS (<= 0xffff) - SSP (within stack range for the CPU) - supervisor token (a single precise address) - padding (zero) The number ranges covered by these classes are entirely disjoint, so qualifying all three slots accordingly can be done without any risk of getting an entry wrong. > 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. How, when there's the return address of this function plus an SSP value preceding it? Jan
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |