Re: [PATCH 00/35] Shadow stacks for userspace

From: Andy Lutomirski
Date: Fri Mar 04 2022 - 14:13:32 EST


On 3/3/22 17:30, Edgecombe, Rick P wrote:
On Thu, 2022-03-03 at 15:00 -0800, Andy Lutomirski wrote:
The intent of PTRACE_CALL_FUNCTION_SIGFRAME is push a signal
frame onto
the stack and call a function. That function should then be able
to call
sigreturn just like any normal signal handler.

Ok, let me reiterate.

We have a seized and stopped tracee, use
PTRACE_CALL_FUNCTION_SIGFRAME
to push a signal frame onto the tracee's stack so that sigreturn
could use
that frame, then set the tracee %rip to the function we'd like to
call and
then we PTRACE_CONT the tracee. Tracee continues to execute the
parasite
code that calls sigreturn to clean up and restore the tracee
process.

PTRACE_CALL_FUNCTION_SIGFRAME also pushes a restore token to the
shadow
stack, just like setup_rt_frame() does, so that sys_rt_sigreturn()
won't
bail out at restore_signal_shadow_stack().

That is the intent.


The only thing that CRIU actually needs is to push a restore token
to the
shadow stack, so for us a ptrace call that does that would be
ideal.


That seems fine too. The main benefit of the SIGFRAME approach is
that, AIUI, CRIU eventually constructs a signal frame anyway, and
getting one ready-made seems plausibly helpful. But if it's not
actually that useful, then there's no need to do it.

I guess pushing a token to the shadow stack could be done like GDB does
calls, with just the basic CET ptrace support. So do we even need a
specific push token operation?

I suppose if CRIU already used some kernel encapsulation of a seized
call/return operation it would have been easier to make CRIU work with
the introduction of CET. But the design of CRIU seems to be to have the
kernel expose just enough and then tie it all together in userspace.

Andy, did you have any other usages for PTRACE_CALL_FUNCTION in mind? I
couldn't find any other CRIU-like users of sigreturn in the debian
source search (but didn't read all 819 pages that come up with
"sigreturn"). It seemed to be mostly seccomp sandbox references.

I don't see a benefit compelling enough to justify the added complexity, given that existing mechanisms can do it.

The sigframe thing, OTOH, seems genuinely useful if CRIU would actually use it to save the full register state. Generating a signal frame from scratch is a pain. That being said, if CRIU isn't excited, then don't bother.