Re: [PATCH v7 32/41] x86/shstk: Handle signals for shadow stack
From: Borislav Petkov <bp@alien8.de>
Date: 2023-03-09 17:07:01
Also in:
linux-arch, linux-doc, linux-mm, lkml
On Mon, Feb 27, 2023 at 02:29:48PM -0800, Rick Edgecombe wrote:
From: Yu-cheng Yu <redacted> 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.
...
quoted hunk ↗ jump to hunk
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.
https://people.kernel.org/tglx/notes-about-netiquette