2017-12-12 11:39:18

by Torsten Duwe

[permalink] [raw]
Subject: [PATCH] On ppc64le we HAVE_RELIABLE_STACKTRACE

Hi all,

The "Power Architecture 64-Bit ELF V2 ABI" says in section 2.3.2.3:

[...] There are several rules that must be adhered to in order to ensure
reliable and consistent call chain backtracing:

* Before a function calls any other function, it shall establish its
own stack frame, whose size shall be a multiple of 16 bytes.

– In instances where a function’s prologue creates a stack frame, the
back-chain word of the stack frame shall be updated atomically with
the value of the stack pointer (r1) when a back chain is implemented.
(This must be supported as default by all ELF V2 ABI-compliant
environments.)
[...]
– The function shall save the link register that contains its return
address in the LR save doubleword of its caller’s stack frame before
calling another function.

To me this sounds like the equivalent of HAVE_RELIABLE_STACKTRACE.
This patch may be unneccessarily limited to ppc64le, but OTOH the only
user of this flag so far is livepatching, which is only implemented on
PPCs with 64-LE, a.k.a. ELF ABI v2.

Signed-off-by: Torsten Duwe <[email protected]>

---
diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig
index c51e6ce42e7a..3e3a6ab2e089 100644
--- a/arch/powerpc/Kconfig
+++ b/arch/powerpc/Kconfig
@@ -218,6 +218,7 @@ config PPC
select HAVE_PERF_USER_STACK_DUMP
select HAVE_RCU_TABLE_FREE if SMP
select HAVE_REGS_AND_STACK_ACCESS_API
+ select HAVE_RELIABLE_STACKTRACE if PPC64 && CPU_LITTLE_ENDIAN
select HAVE_SYSCALL_TRACEPOINTS
select HAVE_VIRT_CPU_ACCOUNTING
select HAVE_IRQ_TIME_ACCOUNTING


2017-12-12 12:12:42

by Miroslav Benes

[permalink] [raw]
Subject: Re: [PATCH] On ppc64le we HAVE_RELIABLE_STACKTRACE

On Tue, 12 Dec 2017, Torsten Duwe wrote:

> Hi all,
>
> The "Power Architecture 64-Bit ELF V2 ABI" says in section 2.3.2.3:
>
> [...] There are several rules that must be adhered to in order to ensure
> reliable and consistent call chain backtracing:
>
> * Before a function calls any other function, it shall establish its
> own stack frame, whose size shall be a multiple of 16 bytes.
>
> – In instances where a function’s prologue creates a stack frame, the
> back-chain word of the stack frame shall be updated atomically with
> the value of the stack pointer (r1) when a back chain is implemented.
> (This must be supported as default by all ELF V2 ABI-compliant
> environments.)
> [...]
> – The function shall save the link register that contains its return
> address in the LR save doubleword of its caller’s stack frame before
> calling another function.
>
> To me this sounds like the equivalent of HAVE_RELIABLE_STACKTRACE.
> This patch may be unneccessarily limited to ppc64le, but OTOH the only
> user of this flag so far is livepatching, which is only implemented on
> PPCs with 64-LE, a.k.a. ELF ABI v2.
>
> Signed-off-by: Torsten Duwe <[email protected]>
>
> ---
> diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig
> index c51e6ce42e7a..3e3a6ab2e089 100644
> --- a/arch/powerpc/Kconfig
> +++ b/arch/powerpc/Kconfig
> @@ -218,6 +218,7 @@ config PPC
> select HAVE_PERF_USER_STACK_DUMP
> select HAVE_RCU_TABLE_FREE if SMP
> select HAVE_REGS_AND_STACK_ACCESS_API
> + select HAVE_RELIABLE_STACKTRACE if PPC64 && CPU_LITTLE_ENDIAN
> select HAVE_SYSCALL_TRACEPOINTS
> select HAVE_VIRT_CPU_ACCOUNTING
> select HAVE_IRQ_TIME_ACCOUNTING

I think that this is not enough. You need to also implement
save_stack_trace_tsk_reliable() for powerpc defined as __weak in
kernel/stacktrace.c. See arch/x86/kernel/stacktrace.c for reference, but I
think it would be much much simpler here given the changelog description.

Thanks,
Miroslav

2017-12-12 13:02:51

by Torsten Duwe

[permalink] [raw]
Subject: Re: [PATCH] On ppc64le we HAVE_RELIABLE_STACKTRACE

On Tue, Dec 12, 2017 at 01:12:37PM +0100, Miroslav Benes wrote:
>
> I think that this is not enough. You need to also implement
> save_stack_trace_tsk_reliable() for powerpc defined as __weak in
> kernel/stacktrace.c. See arch/x86/kernel/stacktrace.c for reference, but I
> think it would be much much simpler here given the changelog description.

Is there an exhaustive, definite, non-x86-centric description of the cases
this function needs to look for? Maybe some sort of formal specification?

Torsten

2017-12-12 14:05:06

by Josh Poimboeuf

[permalink] [raw]
Subject: Re: [PATCH] On ppc64le we HAVE_RELIABLE_STACKTRACE

On Tue, Dec 12, 2017 at 12:39:12PM +0100, Torsten Duwe wrote:
> Hi all,
>
> The "Power Architecture 64-Bit ELF V2 ABI" says in section 2.3.2.3:
>
> [...] There are several rules that must be adhered to in order to ensure
> reliable and consistent call chain backtracing:
>
> * Before a function calls any other function, it shall establish its
> own stack frame, whose size shall be a multiple of 16 bytes.

What about leaf functions? If a leaf function doesn't establish a stack
frame, and it has inline asm which contains a blr to another function,
this ABI is broken.

Also, even for non-leaf functions, is it possible for GCC to insert the
inline asm before it sets up the stack frame? (This is an occasional
problem on x86.)

Also, what about hand-coded asm?

> To me this sounds like the equivalent of HAVE_RELIABLE_STACKTRACE.
> This patch may be unneccessarily limited to ppc64le, but OTOH the only
> user of this flag so far is livepatching, which is only implemented on
> PPCs with 64-LE, a.k.a. ELF ABI v2.

In addition to fixing the above issues, the unwinder also needs to
detect interrupts (i.e., preemption) and page faults on the stack of a
blocked task. If a function were preempted before it created a stack
frame, or if a leaf function blocked on a page fault, the stack trace
will skip the function's caller, so such a trace will need to be
reported to livepatch as unreliable.

Furthermore, the "reliable" unwinder needs to have a way to report an
error if it doesn't reach the end. This probably just means ensuring
that it reaches the user mode registers on the stack.

And as Miroslav mentioned, once that's all done, implement
save_stack_trace_tsk_reliable().

I don't think the above is documented anywhere, it would be good to put
it in the livepatch doc.

--
Josh

2017-12-15 09:40:26

by Nicholas Piggin

[permalink] [raw]
Subject: Re: [PATCH] On ppc64le we HAVE_RELIABLE_STACKTRACE

On Tue, 12 Dec 2017 08:05:01 -0600
Josh Poimboeuf <[email protected]> wrote:

> On Tue, Dec 12, 2017 at 12:39:12PM +0100, Torsten Duwe wrote:
> > Hi all,
> >
> > The "Power Architecture 64-Bit ELF V2 ABI" says in section 2.3.2.3:
> >
> > [...] There are several rules that must be adhered to in order to ensure
> > reliable and consistent call chain backtracing:
> >
> > * Before a function calls any other function, it shall establish its
> > own stack frame, whose size shall be a multiple of 16 bytes.
>
> What about leaf functions? If a leaf function doesn't establish a stack
> frame, and it has inline asm which contains a blr to another function,
> this ABI is broken.
>
> Also, even for non-leaf functions, is it possible for GCC to insert the
> inline asm before it sets up the stack frame? (This is an occasional
> problem on x86.)

Inline asm must not have control transfer out of the statement unless
it is asm goto.

>
> Also, what about hand-coded asm?

Should follow the same rules if it uses the stack.

>
> > To me this sounds like the equivalent of HAVE_RELIABLE_STACKTRACE.
> > This patch may be unneccessarily limited to ppc64le, but OTOH the only
> > user of this flag so far is livepatching, which is only implemented on
> > PPCs with 64-LE, a.k.a. ELF ABI v2.
>
> In addition to fixing the above issues, the unwinder also needs to
> detect interrupts (i.e., preemption) and page faults on the stack of a
> blocked task. If a function were preempted before it created a stack
> frame, or if a leaf function blocked on a page fault, the stack trace
> will skip the function's caller, so such a trace will need to be
> reported to livepatch as unreliable.

I don't think there is much problem there for powerpc. Stack frame
creation and function call with return pointer are each atomic.

>
> Furthermore, the "reliable" unwinder needs to have a way to report an
> error if it doesn't reach the end. This probably just means ensuring
> that it reaches the user mode registers on the stack.
>
> And as Miroslav mentioned, once that's all done, implement
> save_stack_trace_tsk_reliable().
>
> I don't think the above is documented anywhere, it would be good to put
> it in the livepatch doc.
>

Thanks,
Nick

2017-12-18 02:58:58

by Josh Poimboeuf

[permalink] [raw]
Subject: Re: [PATCH] On ppc64le we HAVE_RELIABLE_STACKTRACE

On Fri, Dec 15, 2017 at 07:40:09PM +1000, Nicholas Piggin wrote:
> On Tue, 12 Dec 2017 08:05:01 -0600
> Josh Poimboeuf <[email protected]> wrote:
>
> > On Tue, Dec 12, 2017 at 12:39:12PM +0100, Torsten Duwe wrote:
> > > Hi all,
> > >
> > > The "Power Architecture 64-Bit ELF V2 ABI" says in section 2.3.2.3:
> > >
> > > [...] There are several rules that must be adhered to in order to ensure
> > > reliable and consistent call chain backtracing:
> > >
> > > * Before a function calls any other function, it shall establish its
> > > own stack frame, whose size shall be a multiple of 16 bytes.
> >
> > What about leaf functions? If a leaf function doesn't establish a stack
> > frame, and it has inline asm which contains a blr to another function,
> > this ABI is broken.

Oops, I meant to say "bl" instead of "blr".

> > Also, even for non-leaf functions, is it possible for GCC to insert the
> > inline asm before it sets up the stack frame? (This is an occasional
> > problem on x86.)
>
> Inline asm must not have control transfer out of the statement unless
> it is asm goto.

Can inline asm have calls to other functions?

> > Also, what about hand-coded asm?
>
> Should follow the same rules if it uses the stack.

How is that enforced?

> > > To me this sounds like the equivalent of HAVE_RELIABLE_STACKTRACE.
> > > This patch may be unneccessarily limited to ppc64le, but OTOH the only
> > > user of this flag so far is livepatching, which is only implemented on
> > > PPCs with 64-LE, a.k.a. ELF ABI v2.
> >
> > In addition to fixing the above issues, the unwinder also needs to
> > detect interrupts (i.e., preemption) and page faults on the stack of a
> > blocked task. If a function were preempted before it created a stack
> > frame, or if a leaf function blocked on a page fault, the stack trace
> > will skip the function's caller, so such a trace will need to be
> > reported to livepatch as unreliable.
>
> I don't think there is much problem there for powerpc. Stack frame
> creation and function call with return pointer are each atomic.

What if the function is interrupted before it creates the stack frame?

--
Josh

2017-12-18 03:39:09

by Balbir Singh

[permalink] [raw]
Subject: Re: [PATCH] On ppc64le we HAVE_RELIABLE_STACKTRACE

On Mon, Dec 18, 2017 at 1:58 PM, Josh Poimboeuf <[email protected]> wrote:
> On Fri, Dec 15, 2017 at 07:40:09PM +1000, Nicholas Piggin wrote:
>> On Tue, 12 Dec 2017 08:05:01 -0600
>> Josh Poimboeuf <[email protected]> wrote:
>>
>> > On Tue, Dec 12, 2017 at 12:39:12PM +0100, Torsten Duwe wrote:
>> > > Hi all,
>> > >
>> > > The "Power Architecture 64-Bit ELF V2 ABI" says in section 2.3.2.3:
>> > >
>> > > [...] There are several rules that must be adhered to in order to ensure
>> > > reliable and consistent call chain backtracing:
>> > >
>> > > * Before a function calls any other function, it shall establish its
>> > > own stack frame, whose size shall be a multiple of 16 bytes.
>> >
>> > What about leaf functions? If a leaf function doesn't establish a stack
>> > frame, and it has inline asm which contains a blr to another function,
>> > this ABI is broken.
>
> Oops, I meant to say "bl" instead of "blr".

I was wondering why "blr" mattered, but I guess we should speak of the
consistency
model. By walking a stack trace we expect to find whether a function is in use
or not and can/cannot be live-patched at this point in time. Right?

>
>> > Also, even for non-leaf functions, is it possible for GCC to insert the
>> > inline asm before it sets up the stack frame? (This is an occasional
>> > problem on x86.)
>>
>> Inline asm must not have control transfer out of the statement unless
>> it is asm goto.
>
> Can inline asm have calls to other functions?
>
>> > Also, what about hand-coded asm?
>>
>> Should follow the same rules if it uses the stack.
>
> How is that enforced?
>
>> > > To me this sounds like the equivalent of HAVE_RELIABLE_STACKTRACE.
>> > > This patch may be unneccessarily limited to ppc64le, but OTOH the only
>> > > user of this flag so far is livepatching, which is only implemented on
>> > > PPCs with 64-LE, a.k.a. ELF ABI v2.
>> >
>> > In addition to fixing the above issues, the unwinder also needs to
>> > detect interrupts (i.e., preemption) and page faults on the stack of a
>> > blocked task. If a function were preempted before it created a stack
>> > frame, or if a leaf function blocked on a page fault, the stack trace
>> > will skip the function's caller, so such a trace will need to be
>> > reported to livepatch as unreliable.
>>
>> I don't think there is much problem there for powerpc. Stack frame
>> creation and function call with return pointer are each atomic.
>
> What if the function is interrupted before it creates the stack frame?
>

If it is interrupted, the exception handler will establish a new stack frame.
>From a consistency viewpoint, I guess the question is -- has the function
been entered or considered to be entered when a stack frame has not
yet been established

Balbir Singh.

2017-12-18 04:01:27

by Josh Poimboeuf

[permalink] [raw]
Subject: Re: [PATCH] On ppc64le we HAVE_RELIABLE_STACKTRACE

On Mon, Dec 18, 2017 at 02:39:06PM +1100, Balbir Singh wrote:
> On Mon, Dec 18, 2017 at 1:58 PM, Josh Poimboeuf <[email protected]> wrote:
> > On Fri, Dec 15, 2017 at 07:40:09PM +1000, Nicholas Piggin wrote:
> >> On Tue, 12 Dec 2017 08:05:01 -0600
> >> Josh Poimboeuf <[email protected]> wrote:
> >>
> >> > On Tue, Dec 12, 2017 at 12:39:12PM +0100, Torsten Duwe wrote:
> >> > > Hi all,
> >> > >
> >> > > The "Power Architecture 64-Bit ELF V2 ABI" says in section 2.3.2.3:
> >> > >
> >> > > [...] There are several rules that must be adhered to in order to ensure
> >> > > reliable and consistent call chain backtracing:
> >> > >
> >> > > * Before a function calls any other function, it shall establish its
> >> > > own stack frame, whose size shall be a multiple of 16 bytes.
> >> >
> >> > What about leaf functions? If a leaf function doesn't establish a stack
> >> > frame, and it has inline asm which contains a blr to another function,
> >> > this ABI is broken.
> >
> > Oops, I meant to say "bl" instead of "blr".
>
> I was wondering why "blr" mattered, but I guess we should speak of the
> consistency
> model. By walking a stack trace we expect to find whether a function is in use
> or not and can/cannot be live-patched at this point in time. Right?

Right.

> >> > Also, even for non-leaf functions, is it possible for GCC to insert the
> >> > inline asm before it sets up the stack frame? (This is an occasional
> >> > problem on x86.)
> >>
> >> Inline asm must not have control transfer out of the statement unless
> >> it is asm goto.
> >
> > Can inline asm have calls to other functions?
> >
> >> > Also, what about hand-coded asm?
> >>
> >> Should follow the same rules if it uses the stack.
> >
> > How is that enforced?
> >
> >> > > To me this sounds like the equivalent of HAVE_RELIABLE_STACKTRACE.
> >> > > This patch may be unneccessarily limited to ppc64le, but OTOH the only
> >> > > user of this flag so far is livepatching, which is only implemented on
> >> > > PPCs with 64-LE, a.k.a. ELF ABI v2.
> >> >
> >> > In addition to fixing the above issues, the unwinder also needs to
> >> > detect interrupts (i.e., preemption) and page faults on the stack of a
> >> > blocked task. If a function were preempted before it created a stack
> >> > frame, or if a leaf function blocked on a page fault, the stack trace
> >> > will skip the function's caller, so such a trace will need to be
> >> > reported to livepatch as unreliable.
> >>
> >> I don't think there is much problem there for powerpc. Stack frame
> >> creation and function call with return pointer are each atomic.
> >
> > What if the function is interrupted before it creates the stack frame?
> >
>
> If it is interrupted, the exception handler will establish a new stack frame.
> From a consistency viewpoint, I guess the question is -- has the function
> been entered or considered to be entered when a stack frame has not
> yet been established

Actually I think it's the function's *caller* which gets skipped. r1
(stack pointer) will point to the caller's stack frame, and presumably
the unwinder would read the caller's caller's stack frame to get the
next LR, skipping the caller's return address because it hasn't been
saved yet.

--
Josh

2017-12-18 05:33:49

by Nicholas Piggin

[permalink] [raw]
Subject: Re: [PATCH] On ppc64le we HAVE_RELIABLE_STACKTRACE

On Sun, 17 Dec 2017 20:58:54 -0600
Josh Poimboeuf <[email protected]> wrote:

> On Fri, Dec 15, 2017 at 07:40:09PM +1000, Nicholas Piggin wrote:
> > On Tue, 12 Dec 2017 08:05:01 -0600
> > Josh Poimboeuf <[email protected]> wrote:
> >
> > > On Tue, Dec 12, 2017 at 12:39:12PM +0100, Torsten Duwe wrote:
> > > > Hi all,
> > > >
> > > > The "Power Architecture 64-Bit ELF V2 ABI" says in section 2.3.2.3:
> > > >
> > > > [...] There are several rules that must be adhered to in order to ensure
> > > > reliable and consistent call chain backtracing:
> > > >
> > > > * Before a function calls any other function, it shall establish its
> > > > own stack frame, whose size shall be a multiple of 16 bytes.
> > >
> > > What about leaf functions? If a leaf function doesn't establish a stack
> > > frame, and it has inline asm which contains a blr to another function,
> > > this ABI is broken.
>
> Oops, I meant to say "bl" instead of "blr".
>
> > > Also, even for non-leaf functions, is it possible for GCC to insert the
> > > inline asm before it sets up the stack frame? (This is an occasional
> > > problem on x86.)
> >
> > Inline asm must not have control transfer out of the statement unless
> > it is asm goto.
>
> Can inline asm have calls to other functions?

I don't believe so.

>
> > > Also, what about hand-coded asm?
> >
> > Should follow the same rules if it uses the stack.
>
> How is that enforced?

It's not, AFAIK. Gcc doesn't understand what's inside asm("").

>
> > > > To me this sounds like the equivalent of HAVE_RELIABLE_STACKTRACE.
> > > > This patch may be unneccessarily limited to ppc64le, but OTOH the only
> > > > user of this flag so far is livepatching, which is only implemented on
> > > > PPCs with 64-LE, a.k.a. ELF ABI v2.
> > >
> > > In addition to fixing the above issues, the unwinder also needs to
> > > detect interrupts (i.e., preemption) and page faults on the stack of a
> > > blocked task. If a function were preempted before it created a stack
> > > frame, or if a leaf function blocked on a page fault, the stack trace
> > > will skip the function's caller, so such a trace will need to be
> > > reported to livepatch as unreliable.
> >
> > I don't think there is much problem there for powerpc. Stack frame
> > creation and function call with return pointer are each atomic.
>
> What if the function is interrupted before it creates the stack frame?
>

Then there will be no stack frame, but you still get the caller address
because it's saved in LR register as part of the function call. Then
you get the caller's caller in its stack frame.

Thanks,
Nick

2017-12-18 18:56:25

by Josh Poimboeuf

[permalink] [raw]
Subject: Re: [PATCH] On ppc64le we HAVE_RELIABLE_STACKTRACE

On Mon, Dec 18, 2017 at 03:33:34PM +1000, Nicholas Piggin wrote:
> On Sun, 17 Dec 2017 20:58:54 -0600
> Josh Poimboeuf <[email protected]> wrote:
>
> > On Fri, Dec 15, 2017 at 07:40:09PM +1000, Nicholas Piggin wrote:
> > > On Tue, 12 Dec 2017 08:05:01 -0600
> > > Josh Poimboeuf <[email protected]> wrote:
> > >
> > > > On Tue, Dec 12, 2017 at 12:39:12PM +0100, Torsten Duwe wrote:
> > > > > Hi all,
> > > > >
> > > > > The "Power Architecture 64-Bit ELF V2 ABI" says in section 2.3.2.3:
> > > > >
> > > > > [...] There are several rules that must be adhered to in order to ensure
> > > > > reliable and consistent call chain backtracing:
> > > > >
> > > > > * Before a function calls any other function, it shall establish its
> > > > > own stack frame, whose size shall be a multiple of 16 bytes.
> > > >
> > > > What about leaf functions? If a leaf function doesn't establish a stack
> > > > frame, and it has inline asm which contains a blr to another function,
> > > > this ABI is broken.
> >
> > Oops, I meant to say "bl" instead of "blr".
> >
> > > > Also, even for non-leaf functions, is it possible for GCC to insert the
> > > > inline asm before it sets up the stack frame? (This is an occasional
> > > > problem on x86.)
> > >
> > > Inline asm must not have control transfer out of the statement unless
> > > it is asm goto.
> >
> > Can inline asm have calls to other functions?
>
> I don't believe so.

It's allowed on x86, I don't see why it wouldn't be allowed on powerpc.
As you mentioned, GCC doesn't pay attention to what's inside asm("").

> > > > Also, what about hand-coded asm?
> > >
> > > Should follow the same rules if it uses the stack.
> >
> > How is that enforced?
>
> It's not, AFAIK. Gcc doesn't understand what's inside asm("").

Here I was talking about .S files.

> > > > > To me this sounds like the equivalent of HAVE_RELIABLE_STACKTRACE.
> > > > > This patch may be unneccessarily limited to ppc64le, but OTOH the only
> > > > > user of this flag so far is livepatching, which is only implemented on
> > > > > PPCs with 64-LE, a.k.a. ELF ABI v2.
> > > >
> > > > In addition to fixing the above issues, the unwinder also needs to
> > > > detect interrupts (i.e., preemption) and page faults on the stack of a
> > > > blocked task. If a function were preempted before it created a stack
> > > > frame, or if a leaf function blocked on a page fault, the stack trace
> > > > will skip the function's caller, so such a trace will need to be
> > > > reported to livepatch as unreliable.
> > >
> > > I don't think there is much problem there for powerpc. Stack frame
> > > creation and function call with return pointer are each atomic.
> >
> > What if the function is interrupted before it creates the stack frame?
> >
>
> Then there will be no stack frame, but you still get the caller address
> because it's saved in LR register as part of the function call. Then
> you get the caller's caller in its stack frame.

Ok. So what about the interrupted function itself? Looking at the
powerpc version of save_context_stack(), it doesn't do anything special
for exception frames like checking regs->nip.

Though it looks like that should be possible since show_stack() has a
way to identify exception frames.

--
Josh

2017-12-19 02:46:51

by Nicholas Piggin

[permalink] [raw]
Subject: Re: [PATCH] On ppc64le we HAVE_RELIABLE_STACKTRACE

On Mon, 18 Dec 2017 12:56:22 -0600
Josh Poimboeuf <[email protected]> wrote:

> On Mon, Dec 18, 2017 at 03:33:34PM +1000, Nicholas Piggin wrote:
> > On Sun, 17 Dec 2017 20:58:54 -0600
> > Josh Poimboeuf <[email protected]> wrote:
> >
> > > On Fri, Dec 15, 2017 at 07:40:09PM +1000, Nicholas Piggin wrote:
> > > > On Tue, 12 Dec 2017 08:05:01 -0600
> > > > Josh Poimboeuf <[email protected]> wrote:
> > > >
> > > > > On Tue, Dec 12, 2017 at 12:39:12PM +0100, Torsten Duwe wrote:
> > > > > > Hi all,
> > > > > >
> > > > > > The "Power Architecture 64-Bit ELF V2 ABI" says in section 2.3.2.3:
> > > > > >
> > > > > > [...] There are several rules that must be adhered to in order to ensure
> > > > > > reliable and consistent call chain backtracing:
> > > > > >
> > > > > > * Before a function calls any other function, it shall establish its
> > > > > > own stack frame, whose size shall be a multiple of 16 bytes.
> > > > >
> > > > > What about leaf functions? If a leaf function doesn't establish a stack
> > > > > frame, and it has inline asm which contains a blr to another function,
> > > > > this ABI is broken.
> > >
> > > Oops, I meant to say "bl" instead of "blr".
> > >
> > > > > Also, even for non-leaf functions, is it possible for GCC to insert the
> > > > > inline asm before it sets up the stack frame? (This is an occasional
> > > > > problem on x86.)
> > > >
> > > > Inline asm must not have control transfer out of the statement unless
> > > > it is asm goto.
> > >
> > > Can inline asm have calls to other functions?
> >
> > I don't believe so.
>
> It's allowed on x86, I don't see why it wouldn't be allowed on powerpc.

It's not allowed in general, but there's a lot of architecture specific
differences there, so maybe x86 has an exception. I don't think such an
exception exists for powerpc.... If you know exactly how the code
generation works then you could write inline asm works.

> As you mentioned, GCC doesn't pay attention to what's inside asm("").

And as you mentioned, it doesn't set up the stack frame properly for
leaf functions that call others in asm. There's other concerns too like
different ABI versions (v1/v2) have different stack and calling
conventions.

> > > > > Also, what about hand-coded asm?
> > > >
> > > > Should follow the same rules if it uses the stack.
> > >
> > > How is that enforced?
> >
> > It's not, AFAIK. Gcc doesn't understand what's inside asm("").
>
> Here I was talking about .S files.

Not enforced, but you can assume hand coded asm will not set up a
non-standard stack frame and calling convention, that would be a
bug.

>
> > > > > > To me this sounds like the equivalent of HAVE_RELIABLE_STACKTRACE.
> > > > > > This patch may be unneccessarily limited to ppc64le, but OTOH the only
> > > > > > user of this flag so far is livepatching, which is only implemented on
> > > > > > PPCs with 64-LE, a.k.a. ELF ABI v2.
> > > > >
> > > > > In addition to fixing the above issues, the unwinder also needs to
> > > > > detect interrupts (i.e., preemption) and page faults on the stack of a
> > > > > blocked task. If a function were preempted before it created a stack
> > > > > frame, or if a leaf function blocked on a page fault, the stack trace
> > > > > will skip the function's caller, so such a trace will need to be
> > > > > reported to livepatch as unreliable.
> > > >
> > > > I don't think there is much problem there for powerpc. Stack frame
> > > > creation and function call with return pointer are each atomic.
> > >
> > > What if the function is interrupted before it creates the stack frame?
> > >
> >
> > Then there will be no stack frame, but you still get the caller address
> > because it's saved in LR register as part of the function call. Then
> > you get the caller's caller in its stack frame.
>
> Ok. So what about the interrupted function itself? Looking at the
> powerpc version of save_context_stack(), it doesn't do anything special
> for exception frames like checking regs->nip.
>
> Though it looks like that should be possible since show_stack() has a
> way to identify exception frames.
>

Yes, the low level interrupt code stores a marker in the stack frame
which identifies where an exception occurs.

Thanks,
Nick

2017-12-19 11:28:41

by Torsten Duwe

[permalink] [raw]
Subject: Re: [PATCH] On ppc64le we HAVE_RELIABLE_STACKTRACE

On Mon, Dec 18, 2017 at 12:56:22PM -0600, Josh Poimboeuf wrote:
> On Mon, Dec 18, 2017 at 03:33:34PM +1000, Nicholas Piggin wrote:
> > On Sun, 17 Dec 2017 20:58:54 -0600
> > Josh Poimboeuf <[email protected]> wrote:
> >
> > > On Fri, Dec 15, 2017 at 07:40:09PM +1000, Nicholas Piggin wrote:
> > > > On Tue, 12 Dec 2017 08:05:01 -0600
> > > > Josh Poimboeuf <[email protected]> wrote:
> > > >
> > > > > What about leaf functions? If a leaf function doesn't establish a stack
> > > > > frame, and it has inline asm which contains a blr to another function,
> > > > > this ABI is broken.
> > >
> > > Oops, I meant to say "bl" instead of "blr".

You need to save LR, one way or the other. If gcc thinks it's a leaf function and
does not do it, nor does your asm code, you'll return in an endless loop => bug.

> > > > > Also, even for non-leaf functions, is it possible for GCC to insert the
> > > > > inline asm before it sets up the stack frame? (This is an occasional
> > > > > problem on x86.)
> > > >
> > > > Inline asm must not have control transfer out of the statement unless
> > > > it is asm goto.
> > >
> > > Can inline asm have calls to other functions?
> >
> > I don't believe so.
>
> It's allowed on x86, I don't see why it wouldn't be allowed on powerpc.
> As you mentioned, GCC doesn't pay attention to what's inside asm("").
>
> > > > > Also, what about hand-coded asm?
> > > >
> > > > Should follow the same rules if it uses the stack.
> > >
> > > How is that enforced?
> >
> > It's not, AFAIK. Gcc doesn't understand what's inside asm("").
>
> Here I was talking about .S files.

asm("") or .S ... the ABI spec is clear, and it's quite easy to follow. You
need a place to save LR before you call another function, and STDU is so
convenient to create a stack frame with a single instruction.
My impression is one would have to be very determined to break the ABI
deliberately.


> > > > > In addition to fixing the above issues, the unwinder also needs to
> > > > > detect interrupts (i.e., preemption) and page faults on the stack of a
> > > > > blocked task. If a function were preempted before it created a stack
> > > > > frame, or if a leaf function blocked on a page fault, the stack trace
> > > > > will skip the function's caller, so such a trace will need to be
> > > > > reported to livepatch as unreliable.
> > > >
> > > > I don't think there is much problem there for powerpc. Stack frame
> > > > creation and function call with return pointer are each atomic.
> > >
> > > What if the function is interrupted before it creates the stack frame?

There should be a pt_regs that shows exactly this situation, see below.

> > Then there will be no stack frame, but you still get the caller address
> > because it's saved in LR register as part of the function call. Then
> > you get the caller's caller in its stack frame.
>
> Ok. So what about the interrupted function itself? Looking at the
> powerpc version of save_context_stack(), it doesn't do anything special
> for exception frames like checking regs->nip.
>
> Though it looks like that should be possible since show_stack() has a
> way to identify exception frames.

IIRC x86 errors out if a task was interrupted in kernel context. PPC
save_stack_trace_tsk_reliable() could do the same.

Would that be sufficient?

Torsten

2017-12-19 21:46:58

by Josh Poimboeuf

[permalink] [raw]
Subject: Re: [PATCH] On ppc64le we HAVE_RELIABLE_STACKTRACE

On Tue, Dec 19, 2017 at 12:28:33PM +0100, Torsten Duwe wrote:
> On Mon, Dec 18, 2017 at 12:56:22PM -0600, Josh Poimboeuf wrote:
> > On Mon, Dec 18, 2017 at 03:33:34PM +1000, Nicholas Piggin wrote:
> > > On Sun, 17 Dec 2017 20:58:54 -0600
> > > Josh Poimboeuf <[email protected]> wrote:
> > >
> > > > On Fri, Dec 15, 2017 at 07:40:09PM +1000, Nicholas Piggin wrote:
> > > > > On Tue, 12 Dec 2017 08:05:01 -0600
> > > > > Josh Poimboeuf <[email protected]> wrote:
> > > > >
> > > > > > What about leaf functions? If a leaf function doesn't establish a stack
> > > > > > frame, and it has inline asm which contains a blr to another function,
> > > > > > this ABI is broken.
> > > >
> > > > Oops, I meant to say "bl" instead of "blr".
>
> You need to save LR, one way or the other. If gcc thinks it's a leaf function and
> does not do it, nor does your asm code, you'll return in an endless loop => bug.

Ah, so the function's return path would be corrupted, and an unreliable
stack trace would be the least of our problems.

So it sounds like .c files should be fine, unless I'm missing something
else.

> > > > > > Also, even for non-leaf functions, is it possible for GCC to insert the
> > > > > > inline asm before it sets up the stack frame? (This is an occasional
> > > > > > problem on x86.)
> > > > >
> > > > > Inline asm must not have control transfer out of the statement unless
> > > > > it is asm goto.
> > > >
> > > > Can inline asm have calls to other functions?
> > >
> > > I don't believe so.
> >
> > It's allowed on x86, I don't see why it wouldn't be allowed on powerpc.
> > As you mentioned, GCC doesn't pay attention to what's inside asm("").
> >
> > > > > > Also, what about hand-coded asm?
> > > > >
> > > > > Should follow the same rules if it uses the stack.
> > > >
> > > > How is that enforced?
> > >
> > > It's not, AFAIK. Gcc doesn't understand what's inside asm("").
> >
> > Here I was talking about .S files.
>
> asm("") or .S ... the ABI spec is clear, and it's quite easy to follow. You
> need a place to save LR before you call another function, and STDU is so
> convenient to create a stack frame with a single instruction.
> My impression is one would have to be very determined to break the ABI
> deliberately.

Ok. However, I perused the powerpc crypto code, because that was the
source of a lot of frame pointer breakage in x86. I noticed that some
of the crypto functions create their stack frame *before* writing the LR
to the caller's stack, which is the opposite of what compiled C code
does. That might confuse the unwinder if it were preempted in between.

But more on that below...

> > > > > > In addition to fixing the above issues, the unwinder also needs to
> > > > > > detect interrupts (i.e., preemption) and page faults on the stack of a
> > > > > > blocked task. If a function were preempted before it created a stack
> > > > > > frame, or if a leaf function blocked on a page fault, the stack trace
> > > > > > will skip the function's caller, so such a trace will need to be
> > > > > > reported to livepatch as unreliable.
> > > > >
> > > > > I don't think there is much problem there for powerpc. Stack frame
> > > > > creation and function call with return pointer are each atomic.
> > > >
> > > > What if the function is interrupted before it creates the stack frame?
>
> There should be a pt_regs that shows exactly this situation, see below.
>
> > > Then there will be no stack frame, but you still get the caller address
> > > because it's saved in LR register as part of the function call. Then
> > > you get the caller's caller in its stack frame.
> >
> > Ok. So what about the interrupted function itself? Looking at the
> > powerpc version of save_context_stack(), it doesn't do anything special
> > for exception frames like checking regs->nip.
> >
> > Though it looks like that should be possible since show_stack() has a
> > way to identify exception frames.
>
> IIRC x86 errors out if a task was interrupted in kernel context. PPC
> save_stack_trace_tsk_reliable() could do the same.
>
> Would that be sufficient?

Yes, I think that would cover most of my concerns, including the above
crypto asm issue.

(Otherwise, we'd at least need to make sure that nothing gets skipped by
the unwinder when getting preempted/page faulted in a variety of
scenarios, including before LR is saved to caller, after LR is saved to
caller, the crypto issue I mentioned above, etc)

So with your proposal, I think I'm convinced that we don't need objtool
for ppc64le. Does anyone disagree?

There are still a few more things that need to be looked at:

1) With function graph tracing enabled, is the unwinder smart enough to
get the original function return address, e.g. by calling
ftrace_graph_ret_addr()?

2) Similar question for kretprobes.

3) Any other issues with generated code (e.g., bpf, ftrace trampolines),
runtime patching (e.g., CPU feature alternatives), kprobes, paravirt,
etc, that might confuse the unwinder?

4) As a sanity check, it *might* be a good idea for
save_stack_trace_tsk_reliable() to ensure that it always reaches the
end of the stack. There are several ways to do that:

- If the syscall entry stack frame is always the same size, then the
"end" would simply mean that the stack pointer is at a certain
offset from the end of the task stack page. However this might not
work for kthreads and idle tasks, unless their stacks also start at
the same offset. (On x86 we actually standardized the end of stack
location for all tasks, both user and kernel.)

- If the unwinder can get to the syscall frame, it can presumably
examine regs->msr to check the PR bit to ensure it got all the way
to syscall entry. But again this might only work for user tasks,
depending on how kernel task stacks are set up.

- Or a different approach would be to do error checking along the
way, and reporting an error for any unexpected conditions.

However, given that backlink/LR corruption doesn't seem possible with
this architecture, maybe #4 would be overkill. Personally I would
feel more comfortable with an "end" check and a WARN() if it doesn't
reach the end. But I could just be overly paranoid due to my x86
frame pointer experiences.

--
Josh

2017-12-21 12:10:53

by Michael Ellerman

[permalink] [raw]
Subject: Re: [PATCH] On ppc64le we HAVE_RELIABLE_STACKTRACE

Josh Poimboeuf <[email protected]> writes:

> On Tue, Dec 19, 2017 at 12:28:33PM +0100, Torsten Duwe wrote:
>> On Mon, Dec 18, 2017 at 12:56:22PM -0600, Josh Poimboeuf wrote:
>> > On Mon, Dec 18, 2017 at 03:33:34PM +1000, Nicholas Piggin wrote:
>> > > On Sun, 17 Dec 2017 20:58:54 -0600
>> > > Josh Poimboeuf <[email protected]> wrote:
>> > >
>> > > > On Fri, Dec 15, 2017 at 07:40:09PM +1000, Nicholas Piggin wrote:
>> > > > > On Tue, 12 Dec 2017 08:05:01 -0600
>> > > > > Josh Poimboeuf <[email protected]> wrote:
>> > > > >
>> > > > > > What about leaf functions? If a leaf function doesn't establish a stack
>> > > > > > frame, and it has inline asm which contains a blr to another function,
>> > > > > > this ABI is broken.
>> > > >
>> > > > Oops, I meant to say "bl" instead of "blr".
>>
>> You need to save LR, one way or the other. If gcc thinks it's a leaf function and
>> does not do it, nor does your asm code, you'll return in an endless loop => bug.
>
> Ah, so the function's return path would be corrupted, and an unreliable
> stack trace would be the least of our problems.

That's mostly true.

It is possible to save LR somewhere other than the correct stack slot,
in which case you can return correctly but still confuse the unwinder. A
function can hide its caller that way.

It's stupid and we should never do it, but it's not impossible.

...

> So with your proposal, I think I'm convinced that we don't need objtool
> for ppc64le. Does anyone disagree?

I don't disagree, but I'd be happier if we did have objtool support.

Just because it would give us a lot more certainty that we're doing the
right thing everywhere, including in hand-coded asm and inline asm.

It's easy to write powerpc asm such that stack traces are reliable, but
it is *possible* to break them.

> There are still a few more things that need to be looked at:
>
> 1) With function graph tracing enabled, is the unwinder smart enough to
> get the original function return address, e.g. by calling
> ftrace_graph_ret_addr()?

No I don't think so.

> 2) Similar question for kretprobes.
>
> 3) Any other issues with generated code (e.g., bpf, ftrace trampolines),
> runtime patching (e.g., CPU feature alternatives), kprobes, paravirt,
> etc, that might confuse the unwinder?

We'll have to look, I can't be sure off the top of my head.

> 4) As a sanity check, it *might* be a good idea for
> save_stack_trace_tsk_reliable() to ensure that it always reaches the
> end of the stack. There are several ways to do that:
>
> - If the syscall entry stack frame is always the same size, then the
> "end" would simply mean that the stack pointer is at a certain
> offset from the end of the task stack page. However this might not
> work for kthreads and idle tasks, unless their stacks also start at
> the same offset. (On x86 we actually standardized the end of stack
> location for all tasks, both user and kernel.)

Yeah it differs between user and kernel.

> - If the unwinder can get to the syscall frame, it can presumably
> examine regs->msr to check the PR bit to ensure it got all the way
> to syscall entry. But again this might only work for user tasks,
> depending on how kernel task stacks are set up.

That sounds like a good idea. We could possibly mark the last frame of
kernel tasks somehow.

> - Or a different approach would be to do error checking along the
> way, and reporting an error for any unexpected conditions.
>
> However, given that backlink/LR corruption doesn't seem possible with
> this architecture, maybe #4 would be overkill. Personally I would
> feel more comfortable with an "end" check and a WARN() if it doesn't
> reach the end.

Yeah I agree.

cheers

2017-12-23 04:00:13

by Josh Poimboeuf

[permalink] [raw]
Subject: Re: [PATCH] On ppc64le we HAVE_RELIABLE_STACKTRACE

On Thu, Dec 21, 2017 at 11:10:46PM +1100, Michael Ellerman wrote:
> Josh Poimboeuf <[email protected]> writes:
>
> > On Tue, Dec 19, 2017 at 12:28:33PM +0100, Torsten Duwe wrote:
> >> On Mon, Dec 18, 2017 at 12:56:22PM -0600, Josh Poimboeuf wrote:
> >> > On Mon, Dec 18, 2017 at 03:33:34PM +1000, Nicholas Piggin wrote:
> >> > > On Sun, 17 Dec 2017 20:58:54 -0600
> >> > > Josh Poimboeuf <[email protected]> wrote:
> >> > >
> >> > > > On Fri, Dec 15, 2017 at 07:40:09PM +1000, Nicholas Piggin wrote:
> >> > > > > On Tue, 12 Dec 2017 08:05:01 -0600
> >> > > > > Josh Poimboeuf <[email protected]> wrote:
> >> > > > >
> >> > > > > > What about leaf functions? If a leaf function doesn't establish a stack
> >> > > > > > frame, and it has inline asm which contains a blr to another function,
> >> > > > > > this ABI is broken.
> >> > > >
> >> > > > Oops, I meant to say "bl" instead of "blr".
> >>
> >> You need to save LR, one way or the other. If gcc thinks it's a leaf function and
> >> does not do it, nor does your asm code, you'll return in an endless loop => bug.
> >
> > Ah, so the function's return path would be corrupted, and an unreliable
> > stack trace would be the least of our problems.
>
> That's mostly true.
>
> It is possible to save LR somewhere other than the correct stack slot,
> in which case you can return correctly but still confuse the unwinder. A
> function can hide its caller that way.
>
> It's stupid and we should never do it, but it's not impossible.
>
> ...
>
> > So with your proposal, I think I'm convinced that we don't need objtool
> > for ppc64le. Does anyone disagree?
>
> I don't disagree, but I'd be happier if we did have objtool support.
>
> Just because it would give us a lot more certainty that we're doing the
> right thing everywhere, including in hand-coded asm and inline asm.
>
> It's easy to write powerpc asm such that stack traces are reliable, but
> it is *possible* to break them.

In the unlikely case where some asm code had its own custom stack
format, I guess there are two things which could go wrong:

1) bad LR:

If LR isn't a kernel text address, the unwinder can stop the stack
trace, WARN(), and report an error. Although if we were _extremely_
unlucky and a random leftover text address just happened to be in the
LR slot, then the real function would get skipped in the stack trace.
But even then, it's probably only going to be an asm function getting
skipped, and we don't patch asm functions anyway, so it shouldn't
affect livepatch.

2) bad back chain pointer:

I'm not sure if this is even a reasonable concern. I doubt it. But
if it were to happen, presumably the unwinder would abort the stack
trace after reading the bad value. In this case I think the "end"
check (#4 below) would be sufficient to catch it.

So even if there were some stupid ppc asm code out there with its own
stack magic, it still sounds to me like objtool wouldn't be needed.

> > There are still a few more things that need to be looked at:
> >
> > 1) With function graph tracing enabled, is the unwinder smart enough to
> > get the original function return address, e.g. by calling
> > ftrace_graph_ret_addr()?
>
> No I don't think so.
>
> > 2) Similar question for kretprobes.
> >
> > 3) Any other issues with generated code (e.g., bpf, ftrace trampolines),
> > runtime patching (e.g., CPU feature alternatives), kprobes, paravirt,
> > etc, that might confuse the unwinder?
>
> We'll have to look, I can't be sure off the top of my head.
>
> > 4) As a sanity check, it *might* be a good idea for
> > save_stack_trace_tsk_reliable() to ensure that it always reaches the
> > end of the stack. There are several ways to do that:
> >
> > - If the syscall entry stack frame is always the same size, then the
> > "end" would simply mean that the stack pointer is at a certain
> > offset from the end of the task stack page. However this might not
> > work for kthreads and idle tasks, unless their stacks also start at
> > the same offset. (On x86 we actually standardized the end of stack
> > location for all tasks, both user and kernel.)
>
> Yeah it differs between user and kernel.
>
> > - If the unwinder can get to the syscall frame, it can presumably
> > examine regs->msr to check the PR bit to ensure it got all the way
> > to syscall entry. But again this might only work for user tasks,
> > depending on how kernel task stacks are set up.
>
> That sounds like a good idea. We could possibly mark the last frame of
> kernel tasks somehow.
>
> > - Or a different approach would be to do error checking along the
> > way, and reporting an error for any unexpected conditions.
> >
> > However, given that backlink/LR corruption doesn't seem possible with
> > this architecture, maybe #4 would be overkill. Personally I would
> > feel more comfortable with an "end" check and a WARN() if it doesn't
> > reach the end.
>
> Yeah I agree.

--
Josh

2018-02-27 16:41:57

by Torsten Duwe

[permalink] [raw]
Subject: [PATCH 2/2] ppc64le save_stack_trace_tsk_reliable (Was: HAVE_RELIABLE_STACKTRACE)

On Tue, Dec 12, 2017 at 01:12:37PM +0100, Miroslav Benes wrote:
>
> I think that this is not enough. You need to also implement
> save_stack_trace_tsk_reliable() for powerpc defined as __weak in
> kernel/stacktrace.c.

So here is my initial proposal. I'd really like to get the successful
exit stricter, i.e. hit the initial stack value exactly instead of just
a window. Also, the check for kernel code looks clumsy IMHO. IOW:
Comments more than welcome!

Most of it is Copy&Waste, nonetheless:

Signed-off-by: Torsten Duwe <[email protected]>


diff --git a/arch/powerpc/kernel/stacktrace.c b/arch/powerpc/kernel/stacktrace.c
index d534ed901538..e08af49e71d0 100644
--- a/arch/powerpc/kernel/stacktrace.c
+++ b/arch/powerpc/kernel/stacktrace.c
@@ -13,6 +13,7 @@
#include <linux/export.h>
#include <linux/sched.h>
#include <linux/sched/debug.h>
+#include <linux/sched/task_stack.h>
#include <linux/stacktrace.h>
#include <asm/ptrace.h>
#include <asm/processor.h>
@@ -76,3 +77,58 @@ save_stack_trace_regs(struct pt_regs *regs, struct stack_trace *trace)
save_context_stack(trace, regs->gpr[1], current, 0);
}
EXPORT_SYMBOL_GPL(save_stack_trace_regs);
+
+#ifdef CONFIG_HAVE_RELIABLE_STACKTRACE
+int
+save_stack_trace_tsk_reliable(struct task_struct *tsk,
+ struct stack_trace *trace)
+{
+ unsigned long sp;
+ unsigned long stack_page = (unsigned long)task_stack_page(tsk);
+ /* the last frame (unwinding first) may not yet have saved its LR onto the stack. */
+ int firstframe = 1;
+
+ if (tsk == current)
+ sp = current_stack_pointer();
+ else
+ sp = tsk->thread.ksp;
+
+ if (sp < stack_page + sizeof(struct thread_struct)
+ || sp > stack_page + THREAD_SIZE - STACK_FRAME_OVERHEAD)
+ return 1;
+
+ for (;;) {
+ unsigned long *stack = (unsigned long *) sp;
+ unsigned long newsp, ip;
+
+ newsp = stack[0];
+ /* Stack grows downwards; unwinder may only go up */
+ if (newsp <= sp)
+ return 1;
+
+ if (newsp >= stack_page + THREAD_SIZE)
+ return 1; /* invalid backlink, too far up! */
+
+ /* Examine the saved LR: it must point into kernel code. */
+ ip = stack[STACK_FRAME_LR_SAVE];
+ if ( (ip & 0xEFFF000000000000) != CONFIG_KERNEL_START
+ && !firstframe)
+ return 1;
+ firstframe = 0;
+
+ if (!trace->skip)
+ trace->entries[trace->nr_entries++] = ip;
+ else
+ trace->skip--;
+
+ if (newsp > stack_page + THREAD_SIZE - STACK_FRAME_OVERHEAD)
+ break; /* hit the window for last frame */
+
+ if (trace->nr_entries >= trace->max_entries)
+ return -E2BIG;
+
+ sp = newsp;
+ }
+ return 0;
+}
+#endif /* CONFIG_HAVE_RELIABLE_STACKTRACE */


2018-03-08 21:45:26

by Balbir Singh

[permalink] [raw]
Subject: Re: [PATCH 2/2] ppc64le save_stack_trace_tsk_reliable (Was: HAVE_RELIABLE_STACKTRACE)

On Tue, 27 Feb 2018 17:09:24 +0100
Torsten Duwe <[email protected]> wrote:

> On Tue, Dec 12, 2017 at 01:12:37PM +0100, Miroslav Benes wrote:
> >
> > I think that this is not enough. You need to also implement
> > save_stack_trace_tsk_reliable() for powerpc defined as __weak in
> > kernel/stacktrace.c.
>
> So here is my initial proposal. I'd really like to get the successful
> exit stricter, i.e. hit the initial stack value exactly instead of just
> a window. Also, the check for kernel code looks clumsy IMHO. IOW:
> Comments more than welcome!
>
> Most of it is Copy&Waste, nonetheless:

:)

>
> Signed-off-by: Torsten Duwe <[email protected]>
>
>
> diff --git a/arch/powerpc/kernel/stacktrace.c b/arch/powerpc/kernel/stacktrace.c
> index d534ed901538..e08af49e71d0 100644
> --- a/arch/powerpc/kernel/stacktrace.c
> +++ b/arch/powerpc/kernel/stacktrace.c
> @@ -13,6 +13,7 @@
> #include <linux/export.h>
> #include <linux/sched.h>
> #include <linux/sched/debug.h>
> +#include <linux/sched/task_stack.h>
> #include <linux/stacktrace.h>
> #include <asm/ptrace.h>
> #include <asm/processor.h>
> @@ -76,3 +77,58 @@ save_stack_trace_regs(struct pt_regs *regs, struct stack_trace *trace)
> save_context_stack(trace, regs->gpr[1], current, 0);
> }
> EXPORT_SYMBOL_GPL(save_stack_trace_regs);
> +
> +#ifdef CONFIG_HAVE_RELIABLE_STACKTRACE
> +int
> +save_stack_trace_tsk_reliable(struct task_struct *tsk,
> + struct stack_trace *trace)

Just double checking this is called under the task_rq_lock, so its safe
to call task_stack_page() as opposed to try_get_task_stack()

> +{
> + unsigned long sp;
> + unsigned long stack_page = (unsigned long)task_stack_page(tsk);
> + /* the last frame (unwinding first) may not yet have saved its LR onto the stack. */
> + int firstframe = 1;
> +
> + if (tsk == current)
> + sp = current_stack_pointer();
> + else
> + sp = tsk->thread.ksp;
> +
> + if (sp < stack_page + sizeof(struct thread_struct)
> + || sp > stack_page + THREAD_SIZE - STACK_FRAME_OVERHEAD)
> + return 1;

Some of this is already present in validate_sp(), it also validates
irq stacks, should we just reuse that?

> +
> + for (;;) {
> + unsigned long *stack = (unsigned long *) sp;
> + unsigned long newsp, ip;
> +
> + newsp = stack[0];
> + /* Stack grows downwards; unwinder may only go up */
> + if (newsp <= sp)
> + return 1;
> +
> + if (newsp >= stack_page + THREAD_SIZE)
> + return 1; /* invalid backlink, too far up! */
> +
> + /* Examine the saved LR: it must point into kernel code. */
> + ip = stack[STACK_FRAME_LR_SAVE];
> + if ( (ip & 0xEFFF000000000000) != CONFIG_KERNEL_START
> + && !firstframe)
> + return 1;
> + firstframe = 0;
> +
> + if (!trace->skip)
> + trace->entries[trace->nr_entries++] = ip;
> + else
> + trace->skip--;
> +
> + if (newsp > stack_page + THREAD_SIZE - STACK_FRAME_OVERHEAD)
> + break; /* hit the window for last frame */
> +
> + if (trace->nr_entries >= trace->max_entries)
> + return -E2BIG;
> +
> + sp = newsp;
> + }
> + return 0;
> +}
> +#endif /* CONFIG_HAVE_RELIABLE_STACKTRACE */
>

Looks good to me otherwise.

Acked-by: Balbir Singh <[email protected]>

2018-03-09 15:55:58

by Torsten Duwe

[permalink] [raw]
Subject: Re: [PATCH 2/2] ppc64le save_stack_trace_tsk_reliable (Was: HAVE_RELIABLE_STACKTRACE)

On Fri, 9 Mar 2018 08:43:33 +1100
Balbir Singh <[email protected]> wrote:

> On Tue, 27 Feb 2018 17:09:24 +0100
> Torsten Duwe <[email protected]> wrote:

> > +save_stack_trace_tsk_reliable(struct task_struct *tsk,
> > + struct stack_trace *trace)
>
> Just double checking this is called under the task_rq_lock, so its
> safe to call task_stack_page() as opposed to try_get_task_stack()

Yes. IIRC a comment at the call site mentioned it.

[...]
> > + if (sp < stack_page + sizeof(struct thread_struct)
> > + || sp > stack_page + THREAD_SIZE -
> > STACK_FRAME_OVERHEAD)
> > + return 1;
>
> Some of this is already present in validate_sp(), it also validates
> irq stacks, should we just reuse that?

This goes a bit along one of Josh's points; I'll answer there, OK?

[...]

> Looks good to me otherwise.
>
> Acked-by: Balbir Singh <[email protected]>
Thanks.

Torsten