On Mon, Feb 27, 2023 at 02:29:47PM -0800, Rick Edgecombe wrote: > From: Yu-cheng Yu <yu-cheng.yu@xxxxxxxxx> > > Shadow stacks are normally written to via CALL/RET or specific CET ^ indirectly. > instructions like RSTORSSP/SAVEPREVSSP. However during some Linux > operations the kernel will need to write to directly using the ring-0 only "However, sometimes the kernel will need to..." > WRUSS instruction. > > A shadow stack restore token marks a restore point of the shadow stack, and > the address in a token must point directly above the token, which is within > the same shadow stack. This is distinctively different from other pointers > on the shadow stack, since those pointers point to executable code area. > > Introduce token setup and verify routines. Also introduce WRUSS, which is > a kernel-mode instruction but writes directly to user shadow stack. > > In future patches that enable shadow stack to work with signals, the kernel > will need something to denote the point in the stack where sigreturn may be > called. This will prevent attackers calling sigreturn at arbitrary places > in the stack, in order to help prevent SROP attacks. > > To do this, something that can only be written by the kernel needs to be > placed on the shadow stack. This can be accomplished by setting bit 63 in > the frame written to the shadow stack. Userspace return addresses can't > have this bit set as it is in the kernel range. It is also can't be a s/is // > valid restore token. ... > diff --git a/arch/x86/include/asm/special_insns.h b/arch/x86/include/asm/special_insns.h > index de48d1389936..d6cd9344f6c7 100644 > --- a/arch/x86/include/asm/special_insns.h > +++ b/arch/x86/include/asm/special_insns.h > @@ -202,6 +202,19 @@ static inline void clwb(volatile void *__p) > : [pax] "a" (p)); > } > > +#ifdef CONFIG_X86_USER_SHADOW_STACK > +static inline int write_user_shstk_64(u64 __user *addr, u64 val) > +{ > + asm_volatile_goto("1: wrussq %[val], (%[addr])\n" > + _ASM_EXTABLE(1b, %l[fail]) > + :: [addr] "r" (addr), [val] "r" (val) > + :: fail); > + return 0; > +fail: > + return -EFAULT; Nice! > +} > +#endif /* CONFIG_X86_USER_SHADOW_STACK */ > + > #define nop() asm volatile ("nop") > > static inline void serialize(void) ... > +static int put_shstk_data(u64 __user *addr, u64 data) > +{ > + if (WARN_ON_ONCE(data & BIT(63))) Dunno, maybe something like: /* * A comment explaining what that is... */ #define SHSTK_SIGRETURN_TOKEN BIT_ULL(63) or so? And use that instead of that magical bit 63. -- Regards/Gruss, Boris. https://people.kernel.org/tglx/notes-about-netiquette