Re: [PATCH v7 32/41] x86/shstk: Handle signals for shadow stack

Borislav Petkov
2023-03-09T17:06:59Z

On Mon, Feb 27, 2023 at 02:29:48PM -0800, Rick Edgecombe wrote:
> From: Yu-cheng Yu <yu-cheng.yu@intel.com>
>
> When a signal is handled normally the context is pushed to the stack

s/normally //

> before handling it. For shadow stacks, since the shadow stack only track's

"tracks"

> return addresses, there isn't any state that needs to be pushed. However,
> there are still a few things that need to be done. These things are
> userspace visible and which will be kernel ABI for shadow stacks.

"visible to userspace"

s/which //

> One is to make sure the restorer address is written to shadow stack, since
> the signal handler (if not changing ucontext) returns to the restorer, and
> the restorer calls sigreturn. So add the restorer on the shadow stack
> before handling the signal, so there is not a conflict when the signal
> handler returns to the restorer.
>
> The other thing to do is to place some type of checkable token on the
> thread's shadow stack before handling the signal and check it during
> sigreturn. This is an extra layer of protection to hamper attackers
> calling sigreturn manually as in SROP-like attacks.
>
> For this token we can use the shadow stack data format defined earlier.
^^^

Please use passive voice in your commit message: no "we" or "I", etc.

> Have the data pushed be the previous SSP. In the future the sigreturn
> might want to return back to a different stack. Storing the SSP (instead
> of a restore offset or something) allows for future functionality that
> may want to restore to a different stack.
>
> So, when handling a signal push
> - the SSP pointing in the shadow stack data format
> - the restorer address below the restore token.
>
> In sigreturn, verify SSP is stored in the data format and pop the shadow
> stack.

...

> diff --git a/arch/x86/kernel/shstk.c b/arch/x86/kernel/shstk.c
> index 13c02747386f..40f0a55762a9 100644
> --- a/arch/x86/kernel/shstk.c
> +++ b/arch/x86/kernel/shstk.c
> @@ -232,6 +232,104 @@ static int get_shstk_data(unsigned long *data, unsigned long __user *addr)
> return 0;
> }
>
> +static int shstk_push_sigframe(unsigned long *ssp)
> +{
> + unsigned long target_ssp = *ssp;
> +
> + /* Token must be aligned */
> + if (!IS_ALIGNED(*ssp, 8))
> + return -EINVAL;
> +
> + if (!IS_ALIGNED(target_ssp, 8))
> + return -EINVAL;

Those two statements are identical AFAICT.

> + *ssp -= SS_FRAME_SIZE;
> + if (put_shstk_data((void *__user)*ssp, target_ssp))
> + return -EFAULT;
> +
> + return 0;
> +}

--
Regards/Gruss,
Boris.