linux-arm-kernel.lists.infradead.org archive mirror
 help / color / mirror / Atom feed
From: Mark Rutland <mark.rutland@arm.com>
To: "Madhavan T. Venkataraman" <madvenka@linux.microsoft.com>
Cc: Julien Thierry <jthierry@redhat.com>,
	Catalin Marinas <catalin.marinas@arm.com>,
	Mark Brown <broonie@kernel.org>,
	Josh Poimboeuf <jpoimboe@redhat.com>,
	Miroslav Benes <mbenes@suse.cz>, Will Deacon <will@kernel.org>,
	linux-arm-kernel@lists.infradead.org
Subject: Re: [RFC PATCH 0/3] arm64: Implement reliable stack trace
Date: Mon, 1 Feb 2021 16:02:25 +0000	[thread overview]
Message-ID: <20210201160225.GD66060@C02TD0UTHF1T.local> (raw)
In-Reply-To: <f56612b1-2caa-2949-5154-4993732211a8@linux.microsoft.com>

Hi Madhavan,

On Mon, Feb 01, 2021 at 09:21:43AM -0600, Madhavan T. Venkataraman wrote:
> On 1/28/21 9:26 AM, Josh Poimboeuf wrote:
> >> If we're trusting the compiler we can probably just do that without any
> >> explicit support from the compiler - it should be doing the standard
> >> stuff unless we explicitly ask it to and if it isn't then it might be a
> >> result of a mismatch in assumptions rather than a deliberate decision to
> >> do something non-standard.  My understanding with objtool is that a big
> >> part of the idea is to provide a static check that the binary we end up
> >> with matches the assumptions that we are making so the fact that it's a
> >> separate implementation is important.
> > For C code, even if we trusted the compiler (which we don't), we still
> > have inline asm which the compiler doesn't have any visibility to, which
> > is more than capable of messing up frame pointers (we had several cases
> > of this in x86).
> > 
> > Getting the assembler to annotate which functions are FP could be
> > interesting but:
> > 
> > a) good luck getting the assembler folks to do that; they tend to be
> >    insistent on being ignorant of code semantics;
> > 
> > b) assembly often resembles spaghetti and the concept of a function is
> >    quite fluid; in fact many functions aren't annotated as such.
> 
> OK. Before this whole discussion, I did not know that the compiler cannot be trusted.

I think "the compiler cannot be trusted" is overly strong. We want to
*verify* that the compiler is doing what we expect, which might be more
than what it guarantees to do (and those expectations can change over
time), but it doesn't mean we should try to avoid the compiler wherever
possible.

For assembly I expect we'll need to do /some/ manual annotation (e.g.
for trampolines).

> So, it looks like objtool is definitely needed. However, I believe we can minimize
> the work objtool does by using a shadow stack.
> 
> I read Mark Brown's response to my shadow stack email. I agree with him. The shadow
> stack looks promising.
> 
> So, here is my suggestion for the shadow stack. This is just to start the discussion
> on the shadow stack.

Regarding unwinding, shadow stacks have the same problems as frame
records (considering exceptions/interrupts) in that the primary problem
is knowing *when* they are updated, and knowing *when* the LR is
valid or invalid or duplicated (in a frame record or shadow stack
entry).

Given that, I think that assuming we must use a shadow stack for
reliable unwinding would be jumping the gun.

> Prolog and epilog for C functions
> =================================
> 
> Some shadow stack prolog and epilog are needed. Let us add a new option to the compiler
> to generate extra no-ops at the beginning of a function for the prolog and just before
> return for the epilog so some other entity such as objtool can add its own prolog and
> epilog. This is so we don't have to trust the compiler and can maintain our own prolog
> and epilog.

Why wouldn't we ask the compiler to to this, and just check this in the
tooling?

... and if we can do that, why not just check the frame pointer
manipulation?

Note that functions can have multiple return paths, and there might not
be one epilogue. Also, today some functions can have special-cased
prologues for early checks, e.g.

| function:
| 	CBNZ	X0, _func
| 	RET
| 	STP	X29, X30, [SP, #-FRAME_SIZE]
| 	MOV	X29, X30
| 	...
| 	LDP	X29, X30, [SP], #FRAME_SIZE
| 	RET

... and forcing additional work in those could be detrimental.

> Objtool will check for the no-ops. If they are present, it will replace the no-ops with
> the shadow stack prolog and epilog. It can also check the frame pointer prolog and
> epilog.

I suspect this will interact poorly with patchable-function-entry, which
prefixes each instrumentable function with some NOPs.

> Then, it will set a flag in the symbol table entry of the function to indicate that
> the function has a proper prolog and epilog.

I think this boils down to having a prologue and epilogue check, which
seems sane.

> Prolog and epilog for assembly functions
> ========================================
> 
> The no-ops and frame pointer prolog and epilog can be added to assembly functions manually.
> Objtool will process them as above.
> 
> Decoding
> ========
> 
> To do all this, objtool has to decode only the following instructions.
> 
>         - no-op
>         - return instruction
> 	- store register pair in frame pointer prolog
> 	- load register pair in frame pointer epilog
> 
> This simplifies the objtool part a lot. AFAIK, all instructions in ARM64 are
> 32 bits wide. So, objtool does not have to decode an instruction to know its
> length.
> 
> Objtool has to scan a function for the return instruction to know the location(s)
> of the epilog.

That wouldn't be robust if you consider things like:

| func:
| 	STP	x29, x30, [SP, #-FRAME_SIZE]!
|	MOV	X29, SP
| 	B	__fake_ret
|	LDP	X29, X30, [SP], #FRAME_SIZE
|	RET
| __fake_ret:
| 	BL	x30

... which is the sort of thing we want objtool to catch.

[...]

> Unwinder logic
> ==============
> 
> The unwinder will walk the stack using frame pointers like it does
> currently. As it unwinds the regular stack, it will also unwind the
> shadow stack:
> 
> However, at each step, it needs to perform some additional checks:
> 
>         symbol = lookup symbol table entry for pc
>         if (!symbol)
>                 return -EINVAL;
> 
>         if (symbol does not have proper prolog and epilog)
>                 return -EINVAL;

I think at this point, we haven't gained anything from using a shadow
stack, and I'd much rather we used objtool to gather any metadata needed
to make unwinding reliable without mandating a shadow stack.

Thanks,
Mark.

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

  parent reply	other threads:[~2021-02-01 16:03 UTC|newest]

Thread overview: 52+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2020-10-12 17:26 [RFC PATCH 0/3] arm64: Implement reliable stack trace Mark Brown
2020-10-12 17:26 ` [RFC PATCH 1/3] arm64: remove EL0 exception frame record Mark Brown
2020-10-12 17:26 ` [RFC PATCH 2/3] arm64: stacktrace: Report when we reach the end of the stack Mark Brown
2020-10-13 11:07   ` Mark Rutland
2020-10-12 17:26 ` [RFC PATCH 3/3] arm64: stacktrace: Implement reliable stacktrace Mark Brown
2020-10-13 10:42   ` Mark Brown
2020-10-13 11:42   ` Mark Rutland
2020-10-13 16:12     ` Mark Brown
2020-10-15 13:33   ` Miroslav Benes
2020-10-15 15:57     ` Mark Brown
2020-10-16 10:13       ` Miroslav Benes
2020-10-16 12:30         ` Mark Brown
2020-10-15 13:39 ` [RFC PATCH 0/3] arm64: Implement reliable stack trace Miroslav Benes
2020-10-15 14:16   ` Mark Rutland
2020-10-15 15:49     ` Mark Brown
2020-10-15 21:29       ` Josh Poimboeuf
2020-10-16 11:14         ` Mark Rutland
2020-10-20 10:03           ` Mark Rutland
2020-10-20 15:58             ` Josh Poimboeuf
2020-10-16 12:15         ` Mark Brown
2020-10-19 23:41           ` Josh Poimboeuf
2020-10-20 15:39             ` Mark Brown
2020-10-20 16:28               ` Josh Poimboeuf
2021-01-27 14:02 ` Madhavan T. Venkataraman
2021-01-27 16:40   ` Mark Rutland
2021-01-27 17:11     ` Mark Brown
2021-01-27 17:24   ` Madhavan T. Venkataraman
2021-01-27 19:54 ` Madhavan T. Venkataraman
2021-01-28 14:22   ` Mark Brown
2021-01-28 15:26     ` Josh Poimboeuf
2021-01-29 21:39       ` Madhavan T. Venkataraman
2021-02-01  3:20         ` Madhavan T. Venkataraman
2021-02-01 14:39         ` Mark Brown
2021-01-30  4:38       ` Madhavan T. Venkataraman
2021-02-01 15:21       ` Madhavan T. Venkataraman
2021-02-01 15:46         ` Madhavan T. Venkataraman
2021-02-01 16:02         ` Mark Rutland [this message]
2021-02-01 16:22           ` Mark Brown
2021-02-01 21:40             ` Madhavan T. Venkataraman
2021-02-01 21:38           ` Madhavan T. Venkataraman
2021-02-01 23:00             ` Josh Poimboeuf
2021-02-02  2:29               ` Madhavan T. Venkataraman
2021-02-02  3:36                 ` Josh Poimboeuf
2021-02-02 10:05             ` Mark Rutland
2021-02-02 13:33               ` Madhavan T. Venkataraman
2021-02-02 13:35               ` Madhavan T. Venkataraman
2021-02-02 23:32               ` Madhavan T. Venkataraman
2021-02-03 16:53                 ` Mark Rutland
2021-02-03 19:03                   ` Madhavan T. Venkataraman
2021-02-05  2:36                     ` Madhavan T. Venkataraman
2021-02-01 21:59     ` Madhavan T. Venkataraman
2021-02-02 13:36       ` Mark Brown

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20210201160225.GD66060@C02TD0UTHF1T.local \
    --to=mark.rutland@arm.com \
    --cc=broonie@kernel.org \
    --cc=catalin.marinas@arm.com \
    --cc=jpoimboe@redhat.com \
    --cc=jthierry@redhat.com \
    --cc=linux-arm-kernel@lists.infradead.org \
    --cc=madvenka@linux.microsoft.com \
    --cc=mbenes@suse.cz \
    --cc=will@kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).