From: Joe Lawrence <joe.lawrence@redhat.com> Date: 2019-01-22 15:57:35
This patchset fixes a false negative report (ie, unreliable) from the
ppc64 reliable stack unwinder, discussed here [1] when it may
inadvertently trip over a stale exception marker left on the stack.
The first two patches fix this bug. Nicolai's change clears the marker
from the stack when an exception is finished. The next patch modifies
the unwinder to only look for such on stack elements when the ABI
guarantees that they will actually be initialized.
The final two patches consist of code cleanups that Nicolai and I
spotted during the development of the fixes.
Testing included re-running the original test scenario (loading a
livepatch module on ppc64le) on a 5.0.0-rc2 kernel as well as a RHEL-7
backport. I ran internal tests on the RHEL-7 backport and no new test
failures were introduced. I believe that Nicolai has done the same
with respect to the first patch.
[1] https://lore.kernel.org/lkml/7f468285-b149-37e2-e782-c9e538b997a9@redhat.com/
Joe Lawrence (3):
powerpc/livepatch: relax reliable stack tracer checks for first-frame
powerpc/livepatch: small cleanups in save_stack_trace_tsk_reliable()
powerpc/livepatch: return -ERRNO values in
save_stack_trace_tsk_reliable()
Nicolai Stange (1):
powerpc/64s: Clear on-stack exception marker upon exception return
arch/powerpc/Kconfig | 2 +-
arch/powerpc/kernel/entry_64.S | 7 +++
arch/powerpc/kernel/stacktrace.c | 74 +++++++++++++++++---------------
3 files changed, 47 insertions(+), 36 deletions(-)
--
2.20.1
From: Joe Lawrence <joe.lawrence@redhat.com> Date: 2019-01-22 15:57:39
From: Nicolai Stange <redacted>
The ppc64 specific implementation of the reliable stacktracer,
save_stack_trace_tsk_reliable(), bails out and reports an "unreliable
trace" whenever it finds an exception frame on the stack. Stack frames
are classified as exception frames if the STACK_FRAME_REGS_MARKER magic,
as written by exception prologues, is found at a particular location.
However, as observed by Joe Lawrence, it is possible in practice that
non-exception stack frames can alias with prior exception frames and thus,
that the reliable stacktracer can find a stale STACK_FRAME_REGS_MARKER on
the stack. It in turn falsely reports an unreliable stacktrace and blocks
any live patching transition to finish. Said condition lasts until the
stack frame is overwritten/initialized by function call or other means.
In principle, we could mitigate this by making the exception frame
classification condition in save_stack_trace_tsk_reliable() stronger:
in addition to testing for STACK_FRAME_REGS_MARKER, we could also take into
account that for all exceptions executing on the kernel stack
- their stack frames's backlink pointers always match what is saved
in their pt_regs instance's ->gpr[1] slot and that
- their exception frame size equals STACK_INT_FRAME_SIZE, a value
uncommonly large for non-exception frames.
However, while these are currently true, relying on them would make the
reliable stacktrace implementation more sensitive towards future changes in
the exception entry code. Note that false negatives, i.e. not detecting
exception frames, would silently break the live patching consistency model.
Furthermore, certain other places (diagnostic stacktraces, perf, xmon)
rely on STACK_FRAME_REGS_MARKER as well.
Make the exception exit code clear the on-stack STACK_FRAME_REGS_MARKER
for those exceptions running on the "normal" kernel stack and returning
to kernelspace: because the topmost frame is ignored by the reliable stack
tracer anyway, returns to userspace don't need to take care of clearing
the marker.
Furthermore, as I don't have the ability to test this on Book 3E or
32 bits, limit the change to Book 3S and 64 bits.
Finally, make the HAVE_RELIABLE_STACKTRACE Kconfig option depend on
PPC_BOOK3S_64 for documentation purposes. Before this patch, it depended
on PPC64 && CPU_LITTLE_ENDIAN and because CPU_LITTLE_ENDIAN implies
PPC_BOOK3S_64, there's no functional change here.
Fixes: df78d3f61480 ("powerpc/livepatch: Implement reliable stack tracing for the consistency model")
Reported-by: Joe Lawrence <joe.lawrence@redhat.com>
Signed-off-by: Nicolai Stange <redacted>
Signed-off-by: Joe Lawrence <joe.lawrence@redhat.com>
---
arch/powerpc/Kconfig | 2 +-
arch/powerpc/kernel/entry_64.S | 7 +++++++
2 files changed, 8 insertions(+), 1 deletion(-)
From: Joe Lawrence <joe.lawrence@redhat.com> Date: 2019-01-22 15:57:44
Mostly cosmetic changes:
- Group common stack pointer code at the top
- Simplify the first frame logic
- Code stackframe iteration into for...loop construct
- Check for trace->nr_entries overflow before adding any into the array
Suggested-by: Nicolai Stange <redacted>
Signed-off-by: Joe Lawrence <joe.lawrence@redhat.com>
---
arch/powerpc/kernel/stacktrace.c | 40 +++++++++++---------------------
1 file changed, 14 insertions(+), 26 deletions(-)
@@ -135,14 +126,20 @@ save_stack_trace_tsk_reliable(struct task_struct *tsk,stack_end-=STACK_FRAME_OVERHEAD;}+if(tsk==current)+sp=current_stack_pointer();+else+sp=tsk->thread.ksp;+if(sp<stack_page+sizeof(structthread_struct)||sp>stack_end-STACK_FRAME_MIN_SIZE){return1;}-for(;;){+for(firstframe=true;sp!=stack_end;+firstframe=false,sp=newsp){unsignedlong*stack=(unsignedlong*)sp;-unsignedlongnewsp,ip;+unsignedlongip;/* sanity check: ABI requires SP to be aligned 16 bytes. */if(sp&0xF)
@@ -163,10 +160,8 @@ save_stack_trace_tsk_reliable(struct task_struct *tsk,*restoftheframemaybeuninitialized,continueto*thenext.*/-if(firstframe){-firstframe=0;-gotonext;-}+if(firstframe)+continue;/* Mark stacktraces with exception frames as unreliable. */if(sp<=stack_end-STACK_INT_FRAME_SIZE&&
From: Joe Lawrence <joe.lawrence@redhat.com> Date: 2019-01-22 15:58:10
The bottom-most stack frame (the first to be unwound) may be largely
uninitialized, for the "Power Architecture 64-Bit ELF V2 ABI" only
requires its backchain pointer to be set.
The reliable stack tracer should be careful when verifying this frame:
skip checks on STACK_FRAME_LR_SAVE and STACK_FRAME_MARKER offsets that
may contain uninitialized residual data.
Fixes: df78d3f61480 ("powerpc/livepatch: Implement reliable stack tracing for the consistency model")
Signed-off-by: Joe Lawrence <joe.lawrence@redhat.com>
---
arch/powerpc/kernel/stacktrace.c | 32 ++++++++++++++++++++++++--------
1 file changed, 24 insertions(+), 8 deletions(-)
@@ -142,12 +148,6 @@ save_stack_trace_tsk_reliable(struct task_struct *tsk,if(sp&0xF)return1;-/* Mark stacktraces with exception frames as unreliable. */-if(sp<=stack_end-STACK_INT_FRAME_SIZE&&-stack[STACK_FRAME_MARKER]==STACK_FRAME_REGS_MARKER){-return1;-}-newsp=stack[0];/* Stack grows downwards; unwinder may only go up. */if(newsp<=sp)
@@ -158,11 +158,26 @@ save_stack_trace_tsk_reliable(struct task_struct *tsk,return1;/* invalid backlink, too far up. */}+/*+*Wecanonlytrustthebottomframe'sbacklink,the+*restoftheframemaybeuninitialized,continueto+*thenext.+*/+if(firstframe){+firstframe=0;+gotonext;+}++/* Mark stacktraces with exception frames as unreliable. */+if(sp<=stack_end-STACK_INT_FRAME_SIZE&&+stack[STACK_FRAME_MARKER]==STACK_FRAME_REGS_MARKER){+return1;+}+/* Examine the saved LR: it must point into kernel code. */ip=stack[STACK_FRAME_LR_SAVE];-if(!firstframe&&!__kernel_text_address(ip))+if(!__kernel_text_address(ip))return1;-firstframe=0;/**FIXME:IMHOthesetestsdonotbelongin
From: Joe Lawrence <joe.lawrence@redhat.com> Date: 2019-01-22 15:58:15
To match its x86 counterpart, save_stack_trace_tsk_reliable() should
return -EINVAL in cases that it is currently returning 1. No caller is
currently differentiating non-zero error codes, but let's keep the
arch-specific implementations consistent.
Signed-off-by: Joe Lawrence <joe.lawrence@redhat.com>
---
arch/powerpc/kernel/stacktrace.c | 14 +++++++-------
1 file changed, 7 insertions(+), 7 deletions(-)
@@ -143,16 +143,16 @@ save_stack_trace_tsk_reliable(struct task_struct *tsk,/* sanity check: ABI requires SP to be aligned 16 bytes. */if(sp&0xF)-return1;+return-EINVAL;newsp=stack[0];/* Stack grows downwards; unwinder may only go up. */if(newsp<=sp)-return1;+return-EINVAL;if(newsp!=stack_end&&newsp>stack_end-STACK_FRAME_MIN_SIZE){-return1;/* invalid backlink, too far up. */+return-EINVAL;/* invalid backlink, too far up. */}/*
@@ -166,13 +166,13 @@ save_stack_trace_tsk_reliable(struct task_struct *tsk,/* Mark stacktraces with exception frames as unreliable. */if(sp<=stack_end-STACK_INT_FRAME_SIZE&&stack[STACK_FRAME_MARKER]==STACK_FRAME_REGS_MARKER){-return1;+return-EINVAL;}/* Examine the saved LR: it must point into kernel code. */ip=stack[STACK_FRAME_LR_SAVE];if(!__kernel_text_address(ip))-return1;+return-EINVAL;/**FIXME:IMHOthesetestsdonotbelongin
On Tue, Jan 22, 2019 at 10:57:20AM -0500, Joe Lawrence wrote:
This patchset fixes a false negative report (ie, unreliable) from the
ppc64 reliable stack unwinder, discussed here [1] when it may
inadvertently trip over a stale exception marker left on the stack.
The first two patches fix this bug. Nicolai's change clears the marker
from the stack when an exception is finished. The next patch modifies
the unwinder to only look for such on stack elements when the ABI
guarantees that they will actually be initialized.
The final two patches consist of code cleanups that Nicolai and I
spotted during the development of the fixes.
Testing included re-running the original test scenario (loading a
livepatch module on ppc64le) on a 5.0.0-rc2 kernel as well as a RHEL-7
backport. I ran internal tests on the RHEL-7 backport and no new test
failures were introduced. I believe that Nicolai has done the same
with respect to the first patch.
[1] https://lore.kernel.org/lkml/7f468285-b149-37e2-e782-c9e538b997a9@redhat.com/
Joe Lawrence (3):
powerpc/livepatch: relax reliable stack tracer checks for first-frame
powerpc/livepatch: small cleanups in save_stack_trace_tsk_reliable()
powerpc/livepatch: return -ERRNO values in
save_stack_trace_tsk_reliable()
Nicolai Stange (1):
powerpc/64s: Clear on-stack exception marker upon exception return
arch/powerpc/Kconfig | 2 +-
arch/powerpc/kernel/entry_64.S | 7 +++
arch/powerpc/kernel/stacktrace.c | 74 +++++++++++++++++---------------
3 files changed, 47 insertions(+), 36 deletions(-)
This patchset fixes a false negative report (ie, unreliable) from the
ppc64 reliable stack unwinder, discussed here [1] when it may
inadvertently trip over a stale exception marker left on the stack.
The first two patches fix this bug. Nicolai's change clears the marker
from the stack when an exception is finished. The next patch modifies
the unwinder to only look for such on stack elements when the ABI
guarantees that they will actually be initialized.
The final two patches consist of code cleanups that Nicolai and I
spotted during the development of the fixes.
Testing included re-running the original test scenario (loading a
livepatch module on ppc64le) on a 5.0.0-rc2 kernel as well as a RHEL-7
backport. I ran internal tests on the RHEL-7 backport and no new test
failures were introduced. I believe that Nicolai has done the same
with respect to the first patch.
[1] https://lore.kernel.org/lkml/7f468285-b149-37e2-e782-c9e538b997a9@redhat.com/
Joe Lawrence (3):
powerpc/livepatch: relax reliable stack tracer checks for first-frame
powerpc/livepatch: small cleanups in save_stack_trace_tsk_reliable()
powerpc/livepatch: return -ERRNO values in
save_stack_trace_tsk_reliable()
Nicolai Stange (1):
powerpc/64s: Clear on-stack exception marker upon exception return
Michael, are you fine with this going through LP tree, or do you plan to
take it through yours?
Thanks,
--
Jiri Kosina
SUSE Labs
From: Michael Ellerman <mpe@ellerman.id.au> Date: 2019-01-30 12:22:28
Jiri Kosina [off-list ref] writes:
On Tue, 22 Jan 2019, Joe Lawrence wrote:
quoted
This patchset fixes a false negative report (ie, unreliable) from the
ppc64 reliable stack unwinder, discussed here [1] when it may
inadvertently trip over a stale exception marker left on the stack.
The first two patches fix this bug. Nicolai's change clears the marker
from the stack when an exception is finished. The next patch modifies
the unwinder to only look for such on stack elements when the ABI
guarantees that they will actually be initialized.
The final two patches consist of code cleanups that Nicolai and I
spotted during the development of the fixes.
Testing included re-running the original test scenario (loading a
livepatch module on ppc64le) on a 5.0.0-rc2 kernel as well as a RHEL-7
backport. I ran internal tests on the RHEL-7 backport and no new test
failures were introduced. I believe that Nicolai has done the same
with respect to the first patch.
[1] https://lore.kernel.org/lkml/7f468285-b149-37e2-e782-c9e538b997a9@redhat.com/
Joe Lawrence (3):
powerpc/livepatch: relax reliable stack tracer checks for first-frame
powerpc/livepatch: small cleanups in save_stack_trace_tsk_reliable()
powerpc/livepatch: return -ERRNO values in
save_stack_trace_tsk_reliable()
Nicolai Stange (1):
powerpc/64s: Clear on-stack exception marker upon exception return
Michael, are you fine with this going through LP tree, or do you plan to
take it through yours?
I'm happy to take it, unless there's some reason you'd rather it go via
the LP tree?
I don't have any automated live patch tests, but I assume if it's in
linux-next someone can test it? :)
cheers
From: Michael Ellerman <mpe@ellerman.id.au> Date: 2019-01-30 12:27:09
Joe Lawrence [off-list ref] writes:
From: Nicolai Stange <redacted>
The ppc64 specific implementation of the reliable stacktracer,
save_stack_trace_tsk_reliable(), bails out and reports an "unreliable
trace" whenever it finds an exception frame on the stack. Stack frames
are classified as exception frames if the STACK_FRAME_REGS_MARKER magic,
as written by exception prologues, is found at a particular location.
However, as observed by Joe Lawrence, it is possible in practice that
non-exception stack frames can alias with prior exception frames and thus,
that the reliable stacktracer can find a stale STACK_FRAME_REGS_MARKER on
the stack. It in turn falsely reports an unreliable stacktrace and blocks
any live patching transition to finish. Said condition lasts until the
stack frame is overwritten/initialized by function call or other means.
In principle, we could mitigate this by making the exception frame
classification condition in save_stack_trace_tsk_reliable() stronger:
in addition to testing for STACK_FRAME_REGS_MARKER, we could also take into
account that for all exceptions executing on the kernel stack
- their stack frames's backlink pointers always match what is saved
in their pt_regs instance's ->gpr[1] slot and that
- their exception frame size equals STACK_INT_FRAME_SIZE, a value
uncommonly large for non-exception frames.
However, while these are currently true, relying on them would make the
reliable stacktrace implementation more sensitive towards future changes in
the exception entry code. Note that false negatives, i.e. not detecting
exception frames, would silently break the live patching consistency model.
Furthermore, certain other places (diagnostic stacktraces, perf, xmon)
rely on STACK_FRAME_REGS_MARKER as well.
Make the exception exit code clear the on-stack STACK_FRAME_REGS_MARKER
for those exceptions running on the "normal" kernel stack and returning
to kernelspace: because the topmost frame is ignored by the reliable stack
tracer anyway, returns to userspace don't need to take care of clearing
the marker.
Furthermore, as I don't have the ability to test this on Book 3E or
32 bits, limit the change to Book 3S and 64 bits.
Finally, make the HAVE_RELIABLE_STACKTRACE Kconfig option depend on
PPC_BOOK3S_64 for documentation purposes. Before this patch, it depended
on PPC64 && CPU_LITTLE_ENDIAN and because CPU_LITTLE_ENDIAN implies
PPC_BOOK3S_64, there's no functional change here.
That has nothing to do with the fix and should really be in a separate
patch.
I can split it when applying.
cheers
quoted hunk
Fixes: df78d3f61480 ("powerpc/livepatch: Implement reliable stack tracing for the consistency model")
Reported-by: Joe Lawrence <joe.lawrence@redhat.com>
Signed-off-by: Nicolai Stange <redacted>
Signed-off-by: Joe Lawrence <joe.lawrence@redhat.com>
---
arch/powerpc/Kconfig | 2 +-
arch/powerpc/kernel/entry_64.S | 7 +++++++
2 files changed, 8 insertions(+), 1 deletion(-)
I'm happy to take it, unless there's some reason you'd rather it go via
the LP tree?
As this is more about reliable stack unwinding than live patching per se
(which is only a user of that facility), I'd actually slightly prefer if
it goes via your tree.
Thanks,
--
Jiri Kosina
SUSE Labs
From: Michael Ellerman <mpe@ellerman.id.au> Date: 2019-01-31 05:46:29
Jiri Kosina [off-list ref] writes:
On Wed, 30 Jan 2019, Michael Ellerman wrote:
quoted
I'm happy to take it, unless there's some reason you'd rather it go via
the LP tree?
As this is more about reliable stack unwinding than live patching per se
(which is only a user of that facility), I'd actually slightly prefer if
it goes via your tree.
On Tue, Jan 22, 2019 at 10:57:24AM -0500, Joe Lawrence wrote:
To match its x86 counterpart, save_stack_trace_tsk_reliable() should
return -EINVAL in cases that it is currently returning 1. No caller is
currently differentiating non-zero error codes, but let's keep the
arch-specific implementations consistent.
Signed-off-by: Joe Lawrence <joe.lawrence@redhat.com>
On Tue, Jan 22, 2019 at 10:57:21AM -0500, Joe Lawrence wrote:
quoted hunk
From: Nicolai Stange <redacted>
The ppc64 specific implementation of the reliable stacktracer,
save_stack_trace_tsk_reliable(), bails out and reports an "unreliable
trace" whenever it finds an exception frame on the stack. Stack frames
are classified as exception frames if the STACK_FRAME_REGS_MARKER magic,
as written by exception prologues, is found at a particular location.
However, as observed by Joe Lawrence, it is possible in practice that
non-exception stack frames can alias with prior exception frames and thus,
that the reliable stacktracer can find a stale STACK_FRAME_REGS_MARKER on
the stack. It in turn falsely reports an unreliable stacktrace and blocks
any live patching transition to finish. Said condition lasts until the
stack frame is overwritten/initialized by function call or other means.
In principle, we could mitigate this by making the exception frame
classification condition in save_stack_trace_tsk_reliable() stronger:
in addition to testing for STACK_FRAME_REGS_MARKER, we could also take into
account that for all exceptions executing on the kernel stack
- their stack frames's backlink pointers always match what is saved
in their pt_regs instance's ->gpr[1] slot and that
- their exception frame size equals STACK_INT_FRAME_SIZE, a value
uncommonly large for non-exception frames.
However, while these are currently true, relying on them would make the
reliable stacktrace implementation more sensitive towards future changes in
the exception entry code. Note that false negatives, i.e. not detecting
exception frames, would silently break the live patching consistency model.
Furthermore, certain other places (diagnostic stacktraces, perf, xmon)
rely on STACK_FRAME_REGS_MARKER as well.
Make the exception exit code clear the on-stack STACK_FRAME_REGS_MARKER
for those exceptions running on the "normal" kernel stack and returning
to kernelspace: because the topmost frame is ignored by the reliable stack
tracer anyway, returns to userspace don't need to take care of clearing
the marker.
Furthermore, as I don't have the ability to test this on Book 3E or
32 bits, limit the change to Book 3S and 64 bits.
Finally, make the HAVE_RELIABLE_STACKTRACE Kconfig option depend on
PPC_BOOK3S_64 for documentation purposes. Before this patch, it depended
on PPC64 && CPU_LITTLE_ENDIAN and because CPU_LITTLE_ENDIAN implies
PPC_BOOK3S_64, there's no functional change here.
Fixes: df78d3f61480 ("powerpc/livepatch: Implement reliable stack tracing for the consistency model")
Reported-by: Joe Lawrence <joe.lawrence@redhat.com>
Signed-off-by: Nicolai Stange <redacted>
Signed-off-by: Joe Lawrence <joe.lawrence@redhat.com>
---
arch/powerpc/Kconfig | 2 +-
arch/powerpc/kernel/entry_64.S | 7 +++++++
2 files changed, 8 insertions(+), 1 deletion(-)
On Sat, Feb 2, 2019 at 12:14 PM Balbir Singh [off-list ref] wrote:
On Tue, Jan 22, 2019 at 10:57:21AM -0500, Joe Lawrence wrote:
quoted
From: Nicolai Stange <redacted>
The ppc64 specific implementation of the reliable stacktracer,
save_stack_trace_tsk_reliable(), bails out and reports an "unreliable
trace" whenever it finds an exception frame on the stack. Stack frames
are classified as exception frames if the STACK_FRAME_REGS_MARKER magic,
as written by exception prologues, is found at a particular location.
However, as observed by Joe Lawrence, it is possible in practice that
non-exception stack frames can alias with prior exception frames and thus,
that the reliable stacktracer can find a stale STACK_FRAME_REGS_MARKER on
the stack. It in turn falsely reports an unreliable stacktrace and blocks
any live patching transition to finish. Said condition lasts until the
stack frame is overwritten/initialized by function call or other means.
In principle, we could mitigate this by making the exception frame
classification condition in save_stack_trace_tsk_reliable() stronger:
in addition to testing for STACK_FRAME_REGS_MARKER, we could also take into
account that for all exceptions executing on the kernel stack
- their stack frames's backlink pointers always match what is saved
in their pt_regs instance's ->gpr[1] slot and that
- their exception frame size equals STACK_INT_FRAME_SIZE, a value
uncommonly large for non-exception frames.
However, while these are currently true, relying on them would make the
reliable stacktrace implementation more sensitive towards future changes in
the exception entry code. Note that false negatives, i.e. not detecting
exception frames, would silently break the live patching consistency model.
Furthermore, certain other places (diagnostic stacktraces, perf, xmon)
rely on STACK_FRAME_REGS_MARKER as well.
Make the exception exit code clear the on-stack STACK_FRAME_REGS_MARKER
for those exceptions running on the "normal" kernel stack and returning
to kernelspace: because the topmost frame is ignored by the reliable stack
tracer anyway, returns to userspace don't need to take care of clearing
the marker.
Furthermore, as I don't have the ability to test this on Book 3E or
32 bits, limit the change to Book 3S and 64 bits.
Finally, make the HAVE_RELIABLE_STACKTRACE Kconfig option depend on
PPC_BOOK3S_64 for documentation purposes. Before this patch, it depended
on PPC64 && CPU_LITTLE_ENDIAN and because CPU_LITTLE_ENDIAN implies
PPC_BOOK3S_64, there's no functional change here.
Fixes: df78d3f61480 ("powerpc/livepatch: Implement reliable stack tracing for the consistency model")
Reported-by: Joe Lawrence <joe.lawrence@redhat.com>
Signed-off-by: Nicolai Stange <redacted>
Signed-off-by: Joe Lawrence <joe.lawrence@redhat.com>
---
arch/powerpc/Kconfig | 2 +-
arch/powerpc/kernel/entry_64.S | 7 +++++++
2 files changed, 8 insertions(+), 1 deletion(-)
From: Michael Ellerman <mpe@ellerman.id.au> Date: 2019-02-05 11:24:26
Balbir Singh [off-list ref] writes:
On Sat, Feb 2, 2019 at 12:14 PM Balbir Singh [off-list ref] wrote:
quoted
On Tue, Jan 22, 2019 at 10:57:21AM -0500, Joe Lawrence wrote:
quoted
From: Nicolai Stange <redacted>
The ppc64 specific implementation of the reliable stacktracer,
save_stack_trace_tsk_reliable(), bails out and reports an "unreliable
trace" whenever it finds an exception frame on the stack. Stack frames
are classified as exception frames if the STACK_FRAME_REGS_MARKER magic,
as written by exception prologues, is found at a particular location.
However, as observed by Joe Lawrence, it is possible in practice that
non-exception stack frames can alias with prior exception frames and thus,
that the reliable stacktracer can find a stale STACK_FRAME_REGS_MARKER on
the stack. It in turn falsely reports an unreliable stacktrace and blocks
any live patching transition to finish. Said condition lasts until the
stack frame is overwritten/initialized by function call or other means.
In principle, we could mitigate this by making the exception frame
classification condition in save_stack_trace_tsk_reliable() stronger:
in addition to testing for STACK_FRAME_REGS_MARKER, we could also take into
account that for all exceptions executing on the kernel stack
- their stack frames's backlink pointers always match what is saved
in their pt_regs instance's ->gpr[1] slot and that
- their exception frame size equals STACK_INT_FRAME_SIZE, a value
uncommonly large for non-exception frames.
However, while these are currently true, relying on them would make the
reliable stacktrace implementation more sensitive towards future changes in
the exception entry code. Note that false negatives, i.e. not detecting
exception frames, would silently break the live patching consistency model.
Furthermore, certain other places (diagnostic stacktraces, perf, xmon)
rely on STACK_FRAME_REGS_MARKER as well.
Make the exception exit code clear the on-stack STACK_FRAME_REGS_MARKER
for those exceptions running on the "normal" kernel stack and returning
to kernelspace: because the topmost frame is ignored by the reliable stack
tracer anyway, returns to userspace don't need to take care of clearing
the marker.
Furthermore, as I don't have the ability to test this on Book 3E or
32 bits, limit the change to Book 3S and 64 bits.
Finally, make the HAVE_RELIABLE_STACKTRACE Kconfig option depend on
PPC_BOOK3S_64 for documentation purposes. Before this patch, it depended
on PPC64 && CPU_LITTLE_ENDIAN and because CPU_LITTLE_ENDIAN implies
PPC_BOOK3S_64, there's no functional change here.
Fixes: df78d3f61480 ("powerpc/livepatch: Implement reliable stack tracing for the consistency model")
Reported-by: Joe Lawrence <joe.lawrence@redhat.com>
Signed-off-by: Nicolai Stange <redacted>
Signed-off-by: Joe Lawrence <joe.lawrence@redhat.com>
---
arch/powerpc/Kconfig | 2 +-
arch/powerpc/kernel/entry_64.S | 7 +++++++
2 files changed, 8 insertions(+), 1 deletion(-)
On Tue, Feb 5, 2019 at 10:24 PM Michael Ellerman [off-list ref] wrote:
Balbir Singh [off-list ref] writes:
quoted
On Sat, Feb 2, 2019 at 12:14 PM Balbir Singh [off-list ref] wrote:
quoted
On Tue, Jan 22, 2019 at 10:57:21AM -0500, Joe Lawrence wrote:
quoted
From: Nicolai Stange <redacted>
The ppc64 specific implementation of the reliable stacktracer,
save_stack_trace_tsk_reliable(), bails out and reports an "unreliable
trace" whenever it finds an exception frame on the stack. Stack frames
are classified as exception frames if the STACK_FRAME_REGS_MARKER magic,
as written by exception prologues, is found at a particular location.
However, as observed by Joe Lawrence, it is possible in practice that
non-exception stack frames can alias with prior exception frames and thus,
that the reliable stacktracer can find a stale STACK_FRAME_REGS_MARKER on
the stack. It in turn falsely reports an unreliable stacktrace and blocks
any live patching transition to finish. Said condition lasts until the
stack frame is overwritten/initialized by function call or other means.
In principle, we could mitigate this by making the exception frame
classification condition in save_stack_trace_tsk_reliable() stronger:
in addition to testing for STACK_FRAME_REGS_MARKER, we could also take into
account that for all exceptions executing on the kernel stack
- their stack frames's backlink pointers always match what is saved
in their pt_regs instance's ->gpr[1] slot and that
- their exception frame size equals STACK_INT_FRAME_SIZE, a value
uncommonly large for non-exception frames.
However, while these are currently true, relying on them would make the
reliable stacktrace implementation more sensitive towards future changes in
the exception entry code. Note that false negatives, i.e. not detecting
exception frames, would silently break the live patching consistency model.
Furthermore, certain other places (diagnostic stacktraces, perf, xmon)
rely on STACK_FRAME_REGS_MARKER as well.
Make the exception exit code clear the on-stack STACK_FRAME_REGS_MARKER
for those exceptions running on the "normal" kernel stack and returning
to kernelspace: because the topmost frame is ignored by the reliable stack
tracer anyway, returns to userspace don't need to take care of clearing
the marker.
Furthermore, as I don't have the ability to test this on Book 3E or
32 bits, limit the change to Book 3S and 64 bits.
Finally, make the HAVE_RELIABLE_STACKTRACE Kconfig option depend on
PPC_BOOK3S_64 for documentation purposes. Before this patch, it depended
on PPC64 && CPU_LITTLE_ENDIAN and because CPU_LITTLE_ENDIAN implies
PPC_BOOK3S_64, there's no functional change here.
Fixes: df78d3f61480 ("powerpc/livepatch: Implement reliable stack tracing for the consistency model")
Reported-by: Joe Lawrence <joe.lawrence@redhat.com>
Signed-off-by: Nicolai Stange <redacted>
Signed-off-by: Joe Lawrence <joe.lawrence@redhat.com>
---
arch/powerpc/Kconfig | 2 +-
arch/powerpc/kernel/entry_64.S | 7 +++++++
2 files changed, 8 insertions(+), 1 deletion(-)
Could you please double check, r4 is already 0 at this point
IIUC. So the change might be a simple
std r4,STACK_FRAME_OVERHEAD-16(r1)
r4 is not 0, sorry for the noise
Isn't it?
It is, I seem to be reading the wrong bits and confused myself, had to
re-read mtmsrd to ensure it does not modify RS, just MSR. So I guess
we could reuse r4. Should I send a patch on top of this? I have
limited testing infrastructure at the moment, I could use qemu
Balbir Singh.
From: Michael Ellerman <mpe@ellerman.id.au> Date: 2019-02-06 04:44:57
Balbir Singh [off-list ref] writes:
On Tue, Feb 5, 2019 at 10:24 PM Michael Ellerman [off-list ref] wrote:
quoted
Balbir Singh [off-list ref] writes:
quoted
On Sat, Feb 2, 2019 at 12:14 PM Balbir Singh [off-list ref] wrote:
quoted
On Tue, Jan 22, 2019 at 10:57:21AM -0500, Joe Lawrence wrote:
quoted
From: Nicolai Stange <redacted>
The ppc64 specific implementation of the reliable stacktracer,
save_stack_trace_tsk_reliable(), bails out and reports an "unreliable
trace" whenever it finds an exception frame on the stack. Stack frames
are classified as exception frames if the STACK_FRAME_REGS_MARKER magic,
as written by exception prologues, is found at a particular location.
However, as observed by Joe Lawrence, it is possible in practice that
non-exception stack frames can alias with prior exception frames and thus,
that the reliable stacktracer can find a stale STACK_FRAME_REGS_MARKER on
the stack. It in turn falsely reports an unreliable stacktrace and blocks
any live patching transition to finish. Said condition lasts until the
stack frame is overwritten/initialized by function call or other means.
In principle, we could mitigate this by making the exception frame
classification condition in save_stack_trace_tsk_reliable() stronger:
in addition to testing for STACK_FRAME_REGS_MARKER, we could also take into
account that for all exceptions executing on the kernel stack
- their stack frames's backlink pointers always match what is saved
in their pt_regs instance's ->gpr[1] slot and that
- their exception frame size equals STACK_INT_FRAME_SIZE, a value
uncommonly large for non-exception frames.
However, while these are currently true, relying on them would make the
reliable stacktrace implementation more sensitive towards future changes in
the exception entry code. Note that false negatives, i.e. not detecting
exception frames, would silently break the live patching consistency model.
Furthermore, certain other places (diagnostic stacktraces, perf, xmon)
rely on STACK_FRAME_REGS_MARKER as well.
Make the exception exit code clear the on-stack STACK_FRAME_REGS_MARKER
for those exceptions running on the "normal" kernel stack and returning
to kernelspace: because the topmost frame is ignored by the reliable stack
tracer anyway, returns to userspace don't need to take care of clearing
the marker.
Furthermore, as I don't have the ability to test this on Book 3E or
32 bits, limit the change to Book 3S and 64 bits.
Finally, make the HAVE_RELIABLE_STACKTRACE Kconfig option depend on
PPC_BOOK3S_64 for documentation purposes. Before this patch, it depended
on PPC64 && CPU_LITTLE_ENDIAN and because CPU_LITTLE_ENDIAN implies
PPC_BOOK3S_64, there's no functional change here.
Fixes: df78d3f61480 ("powerpc/livepatch: Implement reliable stack tracing for the consistency model")
Reported-by: Joe Lawrence <joe.lawrence@redhat.com>
Signed-off-by: Nicolai Stange <redacted>
Signed-off-by: Joe Lawrence <joe.lawrence@redhat.com>
---
arch/powerpc/Kconfig | 2 +-
arch/powerpc/kernel/entry_64.S | 7 +++++++
2 files changed, 8 insertions(+), 1 deletion(-)
Could you please double check, r4 is already 0 at this point
IIUC. So the change might be a simple
std r4,STACK_FRAME_OVERHEAD-16(r1)
r4 is not 0, sorry for the noise
Isn't it?
It is, I seem to be reading the wrong bits and confused myself, had to
re-read mtmsrd to ensure it does not modify RS, just MSR. So I guess
we could reuse r4.
Yeah it's a bit hard to follow now that we have the split exit paths for
user vs kernel. r4 does get used on the return to userspace case, by
ACCOUNT_CPU_USER_EXIT(), but for the return to kernel it's still got
zero in it.
Should I send a patch on top of this? I have limited testing
infrastructure at the moment, I could use qemu
I'm not sure. It's a bit fragile relying on the r4 value being zero, it
would be easy to accidentally reuse r4. Though it actually wouldn't
matter as long as r4 never has "regshere" in it.
In fact we could store any random value there, it just needs to not be
the exception marker. eg. we could just stick the SRR0 value in there,
that should never alias with "regshere".
But I think maybe we're over thinking it, the cost of the li is pretty
minimal compared to everything else going on here, and this is only on
the return to kernel case, which is arguably not a super hot path.
cheers
On Wed, Feb 6, 2019 at 3:44 PM Michael Ellerman [off-list ref] wrote:
Balbir Singh [off-list ref] writes:
quoted
On Tue, Feb 5, 2019 at 10:24 PM Michael Ellerman [off-list ref] wrote:
quoted
Balbir Singh [off-list ref] writes:
quoted
On Sat, Feb 2, 2019 at 12:14 PM Balbir Singh [off-list ref] wrote:
quoted
On Tue, Jan 22, 2019 at 10:57:21AM -0500, Joe Lawrence wrote:
quoted
From: Nicolai Stange <redacted>
The ppc64 specific implementation of the reliable stacktracer,
save_stack_trace_tsk_reliable(), bails out and reports an "unreliable
trace" whenever it finds an exception frame on the stack. Stack frames
are classified as exception frames if the STACK_FRAME_REGS_MARKER magic,
as written by exception prologues, is found at a particular location.
However, as observed by Joe Lawrence, it is possible in practice that
non-exception stack frames can alias with prior exception frames and thus,
that the reliable stacktracer can find a stale STACK_FRAME_REGS_MARKER on
the stack. It in turn falsely reports an unreliable stacktrace and blocks
any live patching transition to finish. Said condition lasts until the
stack frame is overwritten/initialized by function call or other means.
In principle, we could mitigate this by making the exception frame
classification condition in save_stack_trace_tsk_reliable() stronger:
in addition to testing for STACK_FRAME_REGS_MARKER, we could also take into
account that for all exceptions executing on the kernel stack
- their stack frames's backlink pointers always match what is saved
in their pt_regs instance's ->gpr[1] slot and that
- their exception frame size equals STACK_INT_FRAME_SIZE, a value
uncommonly large for non-exception frames.
However, while these are currently true, relying on them would make the
reliable stacktrace implementation more sensitive towards future changes in
the exception entry code. Note that false negatives, i.e. not detecting
exception frames, would silently break the live patching consistency model.
Furthermore, certain other places (diagnostic stacktraces, perf, xmon)
rely on STACK_FRAME_REGS_MARKER as well.
Make the exception exit code clear the on-stack STACK_FRAME_REGS_MARKER
for those exceptions running on the "normal" kernel stack and returning
to kernelspace: because the topmost frame is ignored by the reliable stack
tracer anyway, returns to userspace don't need to take care of clearing
the marker.
Furthermore, as I don't have the ability to test this on Book 3E or
32 bits, limit the change to Book 3S and 64 bits.
Finally, make the HAVE_RELIABLE_STACKTRACE Kconfig option depend on
PPC_BOOK3S_64 for documentation purposes. Before this patch, it depended
on PPC64 && CPU_LITTLE_ENDIAN and because CPU_LITTLE_ENDIAN implies
PPC_BOOK3S_64, there's no functional change here.
Fixes: df78d3f61480 ("powerpc/livepatch: Implement reliable stack tracing for the consistency model")
Reported-by: Joe Lawrence <joe.lawrence@redhat.com>
Signed-off-by: Nicolai Stange <redacted>
Signed-off-by: Joe Lawrence <joe.lawrence@redhat.com>
---
arch/powerpc/Kconfig | 2 +-
arch/powerpc/kernel/entry_64.S | 7 +++++++
2 files changed, 8 insertions(+), 1 deletion(-)
Could you please double check, r4 is already 0 at this point
IIUC. So the change might be a simple
std r4,STACK_FRAME_OVERHEAD-16(r1)
r4 is not 0, sorry for the noise
Isn't it?
It is, I seem to be reading the wrong bits and confused myself, had to
re-read mtmsrd to ensure it does not modify RS, just MSR. So I guess
we could reuse r4.
Yeah it's a bit hard to follow now that we have the split exit paths for
user vs kernel. r4 does get used on the return to userspace case, by
ACCOUNT_CPU_USER_EXIT(), but for the return to kernel it's still got
zero in it.
quoted
Should I send a patch on top of this? I have limited testing
infrastructure at the moment, I could use qemu
I'm not sure. It's a bit fragile relying on the r4 value being zero, it
would be easy to accidentally reuse r4. Though it actually wouldn't
matter as long as r4 never has "regshere" in it.
Yep, r4 will eventually get reloaded right below, so unless reuses it
as a scratch register, shouldn't matter
In fact we could store any random value there, it just needs to not be
the exception marker. eg. we could just stick the SRR0 value in there,
that should never alias with "regshere".
But I think maybe we're over thinking it, the cost of the li is pretty
minimal compared to everything else going on here, and this is only on
the return to kernel case, which is arguably not a super hot path.
From: Michael Ellerman <hidden> Date: 2019-02-08 13:02:40
On Tue, 2019-01-22 at 15:57:21 UTC, Joe Lawrence wrote:
From: Nicolai Stange <redacted>
The ppc64 specific implementation of the reliable stacktracer,
save_stack_trace_tsk_reliable(), bails out and reports an "unreliable
trace" whenever it finds an exception frame on the stack. Stack frames
are classified as exception frames if the STACK_FRAME_REGS_MARKER magic,
as written by exception prologues, is found at a particular location.
However, as observed by Joe Lawrence, it is possible in practice that
non-exception stack frames can alias with prior exception frames and thus,
that the reliable stacktracer can find a stale STACK_FRAME_REGS_MARKER on
the stack. It in turn falsely reports an unreliable stacktrace and blocks
any live patching transition to finish. Said condition lasts until the
stack frame is overwritten/initialized by function call or other means.
In principle, we could mitigate this by making the exception frame
classification condition in save_stack_trace_tsk_reliable() stronger:
in addition to testing for STACK_FRAME_REGS_MARKER, we could also take into
account that for all exceptions executing on the kernel stack
- their stack frames's backlink pointers always match what is saved
in their pt_regs instance's ->gpr[1] slot and that
- their exception frame size equals STACK_INT_FRAME_SIZE, a value
uncommonly large for non-exception frames.
However, while these are currently true, relying on them would make the
reliable stacktrace implementation more sensitive towards future changes in
the exception entry code. Note that false negatives, i.e. not detecting
exception frames, would silently break the live patching consistency model.
Furthermore, certain other places (diagnostic stacktraces, perf, xmon)
rely on STACK_FRAME_REGS_MARKER as well.
Make the exception exit code clear the on-stack STACK_FRAME_REGS_MARKER
for those exceptions running on the "normal" kernel stack and returning
to kernelspace: because the topmost frame is ignored by the reliable stack
tracer anyway, returns to userspace don't need to take care of clearing
the marker.
Furthermore, as I don't have the ability to test this on Book 3E or
32 bits, limit the change to Book 3S and 64 bits.
Finally, make the HAVE_RELIABLE_STACKTRACE Kconfig option depend on
PPC_BOOK3S_64 for documentation purposes. Before this patch, it depended
on PPC64 && CPU_LITTLE_ENDIAN and because CPU_LITTLE_ENDIAN implies
PPC_BOOK3S_64, there's no functional change here.
Fixes: df78d3f61480 ("powerpc/livepatch: Implement reliable stack tracing for the consistency model")
Reported-by: Joe Lawrence <joe.lawrence@redhat.com>
Signed-off-by: Nicolai Stange <redacted>
Signed-off-by: Joe Lawrence <joe.lawrence@redhat.com>