Thread (52 messages) 52 messages, 5 authors, 2021-02-05

Re: [RFC PATCH 0/3] arm64: Implement reliable stack trace

From: Mark Rutland <mark.rutland@arm.com>
Date: 2021-02-03 16:55:18

On Tue, Feb 02, 2021 at 05:32:32PM -0600, Madhavan T. Venkataraman wrote:
On 2/2/21 4:05 AM, Mark Rutland wrote:
quoted
I think that practically speaking it's necessary to track all potential
paths through functions that may alter the shadow stack or the shadow
stack pointer to ensure that the manipulation is well-balanced and that
the shadow stack pointer isn't corrupted.

Practically speaking, this requires decoding a significant number of
instructions, and tracing through all potential paths a function may
take.
I thought about it some more since you don't like the shadow stack
that much.
Just to be clear, what I was trying to get across was:

* Whatever we do, we want to verify at compile time that the kernel
  binary matches our expecations, and practically speaking this almost
  certainly means using objtool.

* The analysis that objtool will have to do is not made significantly
  simpler through the use of a shadow stack, as it still needs to track
  all paths though a function, etc.

I'm not averse to using a shadow stack (and clang's SCS is a useful
security feature), I just don't think that it helps much with
compile-time verification, and I don't see a strong reason to mandate it
for livepatching.

[...]
The goal is - even if a function modifies fp and/or does not restore sp to its
correct value at the end, the prolog and epilog should manage it so that everything
works. To do this, the current frame pointer address is stored in fp as well as cur_fp.
Even if fp is modified, cur_fp will still point to the correct frame address.

Prolog
=======

The original prolog is:

- Push fp and return address on the stack
- fp = sp


The new prolog is:

- Save cur_fp on the stack
- Push fp, return address on the stack
- fp = sp
- cur_fp = fp

Epilog
======

The original epilog is:

- Pop fp and return address

The new epilog is:

- sp = cur_fp
- Pop fp and return address
- Restore cur_fp from the stack


I think this is pretty simple.
I'm afraid I don't understand the problem you're trying to solve here.
The epilog you propose is also unsound in the face of asynchronous
exceptions, so I suspect you haven't thought as hard about this as you
need to.

Even if the compiler uses a different prologue/epilogue sequence, we
still need to verify that the rest of the function does nothing to
undermine that.

I think this is merely different rather than simpler, and regardless
this would be an invasive change to compilers.
Unwinder
========

The unwinder will start the stack walk from cur_fp instead of fp. At each frame,
it will use the saved cur_fp instead of the saved fp. 

Also, at each step, it can know if fp was actually changed by the function in
the frame. The unwinder can optionally issue warnings.
So this is just about aditional robustness?

I'm happy to use a shadow stack for /additional/ robustness, I just
don't think a shadow stack alone solves all the other issues that we
need compile time verification for, nor does it solve cases where we
might want metadata generated at compile time.
Compiler issue
===============

This solution is geared towards the kernel only. It assumes that the stack
has a fixed size and alignment so the bottom of the stack can be reached
from the current sp.

So, the compiler has to support two prologs and epilogs, one pair for apps
and one pair for the kernel.

Since this is just a tiny bit of code, I don't think this is a problem.
I suspect it's more compilated than that. Configuration differences like
this can easily double the necessary testing, and are liable to becomer
a maintenance burden, so I don't expect compiler folk are likely to want
to support this unless necessary.

At the moment, I don't think that this solves a real problem, and I
don't think that we need to change this.

In future, we might want to agree some constraints with toolchain folk
if we have specific concerns or pain points, but I don't think we've
actually enumerated those and why we can't solve them through over
means.

Thanks,
Mark.

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help