On Thu, 2023-03-09 at 17:48 +0100, Borislav Petkov wrote: > 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. Dunno here, RSTORSSP/SAVEPREVSSP are kind of direct. > > > 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..." Ok. > > > 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 // Yep, thanks. > > > 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. Seems very reasonable. Since we are calling this the "data format", I might go with SHSTK_DATA_BIT.