diff mbox

KASAN issues with idle / hotplug area (was: Re: [PATCH v5sub1 7/8] arm64: move kernel image to base of vmalloc area)

Message ID 20160217170110.GE32647@leverpostej
State New
Headers show

Commit Message

Mark Rutland Feb. 17, 2016, 5:01 p.m. UTC
On Wed, Feb 17, 2016 at 02:39:51PM +0000, Mark Rutland wrote:
> When we go down for idle, in __cpu_suspend_enter we stash some context

> to the stack (in assembly). The CPU may return from a cold state via

> cpu_resume, where we restore context from the stack.

> 

> However, after storing the context we call psci_suspend_finisher, which

> calls psci_cpu_suspend, which calls invoke_psci_fn_*. As

> psci_cpu_suspend and invoke_psci_fn_* are instrumented, they poison

> memory on function entrance, but we never perform the unpoisoning.

> 

> That was always the case for psci_suspend_finisher, so there was a

> latent issue that we were somehow avoiding. Perhaps we got luck with

> stack layout and never hit the poison.

> 

> I'm not sure how we fix that, as invoke_psci_fn_* may or may not return

> for arbitrary reasons (e.g. a CPU_SUSPEND_CALL may or may not return

> depending on whether an interrupt comes in at the right time).

> 

> Perhaps the simplest option is to not instrument invoke_psci_fn_* and

> psci_suspend_finisher. Do we have a per-function annotation to avoid

> KASAN instrumentation, like notrace? I need to investigate, but we may

> also need notrace for similar reasons.


I found __no_sanitize_address.

As an aside, could we rename that to nokasan? That would match the style
of notrace, is just as clear, and would make it far easier to write
consistent legible function prototypes...

Otherwise, I came up with the patch below, per the reasoning above.

It _changes_ the KASAN splats (I see errors in tick_program_event rather
than find_busiest_group), but doesn't seem to get rid of them. I'm not
sure if I've missed something, or if we also have another latent issue.

Ideas?

Mark.

---->8----
From 8f7ae44d8f8862f5300483d45617b5bd05fc652f Mon Sep 17 00:00:00 2001
From: Mark Rutland <mark.rutland@arm.com>

Date: Wed, 17 Feb 2016 15:38:22 +0000
Subject: [PATCH] arm64/psci: avoid KASAN splats with idle

When a CPU goes into a deep idle state, we store CPU context in
__cpu_suspend_enter, then call psci_suspend_finisher to invoke the
firmware. If we entered a deep idle state, we do not return directly,
and instead start cold, restoring state in cpu_resume.

Thus we may execute the prologue and body of psci_suspend_finisher and
the PSCI invocation function, but not their epilogue. When using KASAN
this means that we poison a region of shadow memory, but never unpoison
it. After we resume, subsequent stack accesses may hit the stale poison
values, leading to false positives from KASAN.

To avoid this, we must ensure that functions called after the context
save are not instrumented, and do not posion the shadow region, by
annotating them with __no_sanitize_address. As common inlines they may
call are not similarly annotated, and the compiler refuses to allow
function attribute mismatches, we must also avoid calls to such
functions.

ARM is not affected, as it does not support KASAN. When CONFIG_KASAN is
not selected, __no_sanitize_address expands to nothing, so the
annotation should not be harmful.

Signed-off-by: Mark Rutland <mark.rutland@arm.com>

---
 arch/arm64/kernel/psci.c | 14 ++++++++------
 drivers/firmware/psci.c  |  3 +++
 2 files changed, 11 insertions(+), 6 deletions(-)

-- 
1.9.1


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

Comments

Mark Rutland Feb. 17, 2016, 5:56 p.m. UTC | #1
On Wed, Feb 17, 2016 at 05:01:11PM +0000, Mark Rutland wrote:
> On Wed, Feb 17, 2016 at 02:39:51PM +0000, Mark Rutland wrote:

> > Perhaps the simplest option is to not instrument invoke_psci_fn_* and

> > psci_suspend_finisher. Do we have a per-function annotation to avoid

> > KASAN instrumentation, like notrace? I need to investigate, but we may

> > also need notrace for similar reasons.

>

> I came up with the patch below, per the reasoning above.

> 

> It _changes_ the KASAN splats (I see errors in tick_program_event rather

> than find_busiest_group), but doesn't seem to get rid of them. I'm not

> sure if I've missed something, or if we also have another latent issue.

> 

> Ideas?


I'd missed annotating __cpu_suspend_save. I've fixed that up locally
(along with s/virt_to_phys/__virt_to_phys due to the inlining issue).

I'm still missing somehing; I'm getting KASAN warnings in find_busiest_group
again, and the shadow looks like it's corrupt (the second batch of f3 /
KASAN_STACK_RIGHT don't have a matching f1 / KASAN_STACK_LEFT):

[   13.138791] Memory state around the buggy address:
[   13.143624]  ffffffc936a7fb80: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
[   13.150929]  ffffffc936a7fc00: 00 00 00 00 00 00 00 00 f1 f1 f1 f1 00 00 00 00
[   13.158232] >ffffffc936a7fc80: f3 f3 f3 f3 00 00 00 00 00 f4 f4 f4 f3 f3 f3 f3
[   13.165530]                       ^
[   13.169066]  ffffffc936a7fd00: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
[   13.176369]  ffffffc936a7fd80: 00 00 00 00 00 00 00 00 00 00 00 00 f1 f1 f1 f1

This is turning into a whack-a-mole game...

Mark.

> ---->8----

> From 8f7ae44d8f8862f5300483d45617b5bd05fc652f Mon Sep 17 00:00:00 2001

> From: Mark Rutland <mark.rutland@arm.com>

> Date: Wed, 17 Feb 2016 15:38:22 +0000

> Subject: [PATCH] arm64/psci: avoid KASAN splats with idle

> 

> When a CPU goes into a deep idle state, we store CPU context in

> __cpu_suspend_enter, then call psci_suspend_finisher to invoke the

> firmware. If we entered a deep idle state, we do not return directly,

> and instead start cold, restoring state in cpu_resume.

> 

> Thus we may execute the prologue and body of psci_suspend_finisher and

> the PSCI invocation function, but not their epilogue. When using KASAN

> this means that we poison a region of shadow memory, but never unpoison

> it. After we resume, subsequent stack accesses may hit the stale poison

> values, leading to false positives from KASAN.

> 

> To avoid this, we must ensure that functions called after the context

> save are not instrumented, and do not posion the shadow region, by

> annotating them with __no_sanitize_address. As common inlines they may

> call are not similarly annotated, and the compiler refuses to allow

> function attribute mismatches, we must also avoid calls to such

> functions.

> 

> ARM is not affected, as it does not support KASAN. When CONFIG_KASAN is

> not selected, __no_sanitize_address expands to nothing, so the

> annotation should not be harmful.

> 

> Signed-off-by: Mark Rutland <mark.rutland@arm.com>

> ---

>  arch/arm64/kernel/psci.c | 14 ++++++++------

>  drivers/firmware/psci.c  |  3 +++

>  2 files changed, 11 insertions(+), 6 deletions(-)

> 

> diff --git a/arch/arm64/kernel/psci.c b/arch/arm64/kernel/psci.c

> index f67f35b..8324ce8 100644

> --- a/arch/arm64/kernel/psci.c

> +++ b/arch/arm64/kernel/psci.c

> @@ -32,12 +32,16 @@

>  

>  static DEFINE_PER_CPU_READ_MOSTLY(u32 *, psci_power_state);

>  

> +static phys_addr_t cpu_resume_phys;

> +

>  static int __maybe_unused cpu_psci_cpu_init_idle(unsigned int cpu)

>  {

>  	int i, ret, count = 0;

>  	u32 *psci_states;

>  	struct device_node *state_node, *cpu_node;

>  

> +	cpu_resume_phys = virt_to_phys(cpu_resume);

> +

>  	cpu_node = of_get_cpu_node(cpu, NULL);

>  	if (!cpu_node)

>  		return -ENODEV;

> @@ -178,12 +182,10 @@ static int cpu_psci_cpu_kill(unsigned int cpu)

>  }

>  #endif

>  

> -static int psci_suspend_finisher(unsigned long index)

> +__no_sanitize_address

> +static int psci_suspend_finisher(unsigned long state)

>  {

> -	u32 *state = __this_cpu_read(psci_power_state);

> -

> -	return psci_ops.cpu_suspend(state[index - 1],

> -				    virt_to_phys(cpu_resume));

> +	return psci_ops.cpu_suspend(state, cpu_resume_phys);

>  }

>  

>  static int __maybe_unused cpu_psci_cpu_suspend(unsigned long index)

> @@ -200,7 +202,7 @@ static int __maybe_unused cpu_psci_cpu_suspend(unsigned long index)

>  	if (!psci_power_state_loses_context(state[index - 1]))

>  		ret = psci_ops.cpu_suspend(state[index - 1], 0);

>  	else

> -		ret = cpu_suspend(index, psci_suspend_finisher);

> +		ret = cpu_suspend(state[index - 1], psci_suspend_finisher);

>  

>  	return ret;

>  }

> diff --git a/drivers/firmware/psci.c b/drivers/firmware/psci.c

> index f25cd79..e4e8dc1 100644

> --- a/drivers/firmware/psci.c

> +++ b/drivers/firmware/psci.c

> @@ -106,6 +106,7 @@ bool psci_power_state_is_valid(u32 state)

>  	return !(state & ~valid_mask);

>  }

>  

> +__no_sanitize_address

>  static unsigned long __invoke_psci_fn_hvc(unsigned long function_id,

>  			unsigned long arg0, unsigned long arg1,

>  			unsigned long arg2)

> @@ -116,6 +117,7 @@ static unsigned long __invoke_psci_fn_hvc(unsigned long function_id,

>  	return res.a0;

>  }

>  

> +__no_sanitize_address

>  static unsigned long __invoke_psci_fn_smc(unsigned long function_id,

>  			unsigned long arg0, unsigned long arg1,

>  			unsigned long arg2)

> @@ -148,6 +150,7 @@ static u32 psci_get_version(void)

>  	return invoke_psci_fn(PSCI_0_2_FN_PSCI_VERSION, 0, 0, 0);

>  }

>  

> +__no_sanitize_address

>  static int psci_cpu_suspend(u32 state, unsigned long entry_point)

>  {

>  	int err;

> -- 

> 1.9.1

> 

> 

> _______________________________________________

> linux-arm-kernel mailing list

> linux-arm-kernel@lists.infradead.org

> http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

> 


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
Mark Rutland Feb. 17, 2016, 7:16 p.m. UTC | #2
On Wed, Feb 17, 2016 at 05:56:56PM +0000, Mark Rutland wrote:
> On Wed, Feb 17, 2016 at 05:01:11PM +0000, Mark Rutland wrote:

> > On Wed, Feb 17, 2016 at 02:39:51PM +0000, Mark Rutland wrote:

> > > Perhaps the simplest option is to not instrument invoke_psci_fn_* and

> > > psci_suspend_finisher. Do we have a per-function annotation to avoid

> > > KASAN instrumentation, like notrace? I need to investigate, but we may

> > > also need notrace for similar reasons.

> >

> > I came up with the patch below, per the reasoning above.

> > 

> > It _changes_ the KASAN splats (I see errors in tick_program_event rather

> > than find_busiest_group), but doesn't seem to get rid of them. I'm not

> > sure if I've missed something, or if we also have another latent issue.

> > 

> > Ideas?

> 

> I'd missed annotating __cpu_suspend_save. I've fixed that up locally

> (along with s/virt_to_phys/__virt_to_phys due to the inlining issue).


Thinking about it more, I shouldn't have to annotate __cpu_suspend_save,
as it returns (and hence should have cleaned up after itself).

Looking at the assembly, functions seem to get instrumented regardless
of the __no_sanitize_address annotation. The assembly of
__invoke_psci_fn_{smc,hvc} look identical, even if one has the
annotation and one does not.

In the case below, it looks like __invoke_psci_fn_hvc is storing to the
shadow area even though it's anotated with __no_sanitize_address.  Note
that the adrp symbol resolution is bogus; psci_to_linux_errno happens to
be at offset 0 in the as-yet unlinked psci.o object.

0000000000000420 <__invoke_psci_fn_hvc>:
 420:   d10283ff        sub     sp, sp, #0xa0
 424:   90000004        adrp    x4, 0 <psci_to_linux_errno>
 428:   91000084        add     x4, x4, #0x0
 42c:   90000005        adrp    x5, 0 <psci_to_linux_errno>
 430:   910000a5        add     x5, x5, #0x0
 434:   d2800007        mov     x7, #0x0                        // #0
 438:   a9017bfd        stp     x29, x30, [sp,#16]
 43c:   910043fd        add     x29, sp, #0x10
 440:   d2800006        mov     x6, #0x0                        // #0
 444:   a90253f3        stp     x19, x20, [sp,#32]
 448:   9100c3b3        add     x19, x29, #0x30
 44c:   d2dff214        mov     x20, #0xff9000000000            // #280993940373504
 450:   a90393a5        stp     x5, x4, [x29,#56]
 454:   f2fbfff4        movk    x20, #0xdfff, lsl #48
 458:   d343fe73        lsr     x19, x19, #3
 45c:   d2915664        mov     x4, #0x8ab3                     // #35507
 460:   f9001bf5        str     x21, [sp,#48]
 464:   f2a836a4        movk    x4, #0x41b5, lsl #16
 468:   8b140275        add     x21, x19, x20
 46c:   f9001ba4        str     x4, [x29,#48]
 470:   3204d3e4        mov     w4, #0xf1f1f1f1                 // #-235802127
 474:   b8346a64        str     w4, [x19,x20]
 478:   3204d7e4        mov     w4, #0xf3f3f3f3                 // #-202116109
 47c:   b9000aa4        str     w4, [x21,#8]
 480:   910143a4        add     x4, x29, #0x50
 484:   d2800005        mov     x5, #0x0                        // #0
 488:   f90003e4        str     x4, [sp]
 48c:   d2800004        mov     x4, #0x0                        // #0
 490:   94000000        bl      0 <arm_smccc_hvc>
 494:   f9402ba0        ldr     x0, [x29,#80]
 498:   910003bf        mov     sp, x29
 49c:   b8346a7f        str     wzr, [x19,x20]
 4a0:   b9000abf        str     wzr, [x21,#8]
 4a4:   a94153f3        ldp     x19, x20, [sp,#16]
 4a8:   f94013f5        ldr     x21, [sp,#32]
 4ac:   a8c97bfd        ldp     x29, x30, [sp],#144
 4b0:   d65f03c0        ret
 4b4:   d503201f        nop

For comparison, without KASAN __incoke_psci_fn_hvc looks like:

0000000000000280 <__invoke_psci_fn_hvc>:
 280:   d10103ff        sub     sp, sp, #0x40
 284:   d2800007        mov     x7, #0x0                        // #0
 288:   d2800006        mov     x6, #0x0                        // #0
 28c:   d2800005        mov     x5, #0x0                        // #0
 290:   a9017bfd        stp     x29, x30, [sp,#16]
 294:   910043fd        add     x29, sp, #0x10
 298:   910043a4        add     x4, x29, #0x10
 29c:   f90003e4        str     x4, [sp]
 2a0:   d2800004        mov     x4, #0x0                        // #0
 2a4:   94000000        bl      0 <arm_smccc_hvc>
 2a8:   910003bf        mov     sp, x29
 2ac:   f9400ba0        ldr     x0, [x29,#16]
 2b0:   a8c37bfd        ldp     x29, x30, [sp],#48
 2b4:   d65f03c0        ret

I also tried using __attribute__((no_sanitize_address)) directly, in
case there was some header issue, but that doesn't seem to be the case.

I'm using the Linaro 15.08 AArch64 GCC 5.1. Is anyone else able to
confirm whether they see the same? Does the same happen for x86?

Thanks,
Mark.

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
Ard Biesheuvel Feb. 18, 2016, 8:06 a.m. UTC | #3
On 17 February 2016 at 20:16, Mark Rutland <mark.rutland@arm.com> wrote:
> On Wed, Feb 17, 2016 at 05:56:56PM +0000, Mark Rutland wrote:

>> On Wed, Feb 17, 2016 at 05:01:11PM +0000, Mark Rutland wrote:

>> > On Wed, Feb 17, 2016 at 02:39:51PM +0000, Mark Rutland wrote:

>> > > Perhaps the simplest option is to not instrument invoke_psci_fn_* and

>> > > psci_suspend_finisher. Do we have a per-function annotation to avoid

>> > > KASAN instrumentation, like notrace? I need to investigate, but we may

>> > > also need notrace for similar reasons.

>> >

>> > I came up with the patch below, per the reasoning above.

>> >

>> > It _changes_ the KASAN splats (I see errors in tick_program_event rather

>> > than find_busiest_group), but doesn't seem to get rid of them. I'm not

>> > sure if I've missed something, or if we also have another latent issue.

>> >

>> > Ideas?

>>

>> I'd missed annotating __cpu_suspend_save. I've fixed that up locally

>> (along with s/virt_to_phys/__virt_to_phys due to the inlining issue).

>

> Thinking about it more, I shouldn't have to annotate __cpu_suspend_save,

> as it returns (and hence should have cleaned up after itself).

>

> Looking at the assembly, functions seem to get instrumented regardless

> of the __no_sanitize_address annotation. The assembly of

> __invoke_psci_fn_{smc,hvc} look identical, even if one has the

> annotation and one does not.

>

> In the case below, it looks like __invoke_psci_fn_hvc is storing to the

> shadow area even though it's anotated with __no_sanitize_address.  Note

> that the adrp symbol resolution is bogus; psci_to_linux_errno happens to

> be at offset 0 in the as-yet unlinked psci.o object.

>

> 0000000000000420 <__invoke_psci_fn_hvc>:

>  420:   d10283ff        sub     sp, sp, #0xa0

>  424:   90000004        adrp    x4, 0 <psci_to_linux_errno>

>  428:   91000084        add     x4, x4, #0x0

>  42c:   90000005        adrp    x5, 0 <psci_to_linux_errno>

>  430:   910000a5        add     x5, x5, #0x0

>  434:   d2800007        mov     x7, #0x0                        // #0

>  438:   a9017bfd        stp     x29, x30, [sp,#16]

>  43c:   910043fd        add     x29, sp, #0x10

>  440:   d2800006        mov     x6, #0x0                        // #0

>  444:   a90253f3        stp     x19, x20, [sp,#32]

>  448:   9100c3b3        add     x19, x29, #0x30

>  44c:   d2dff214        mov     x20, #0xff9000000000            // #280993940373504

>  450:   a90393a5        stp     x5, x4, [x29,#56]

>  454:   f2fbfff4        movk    x20, #0xdfff, lsl #48

>  458:   d343fe73        lsr     x19, x19, #3

>  45c:   d2915664        mov     x4, #0x8ab3                     // #35507

>  460:   f9001bf5        str     x21, [sp,#48]

>  464:   f2a836a4        movk    x4, #0x41b5, lsl #16

>  468:   8b140275        add     x21, x19, x20

>  46c:   f9001ba4        str     x4, [x29,#48]

>  470:   3204d3e4        mov     w4, #0xf1f1f1f1                 // #-235802127

>  474:   b8346a64        str     w4, [x19,x20]

>  478:   3204d7e4        mov     w4, #0xf3f3f3f3                 // #-202116109

>  47c:   b9000aa4        str     w4, [x21,#8]

>  480:   910143a4        add     x4, x29, #0x50

>  484:   d2800005        mov     x5, #0x0                        // #0

>  488:   f90003e4        str     x4, [sp]

>  48c:   d2800004        mov     x4, #0x0                        // #0

>  490:   94000000        bl      0 <arm_smccc_hvc>

>  494:   f9402ba0        ldr     x0, [x29,#80]

>  498:   910003bf        mov     sp, x29

>  49c:   b8346a7f        str     wzr, [x19,x20]

>  4a0:   b9000abf        str     wzr, [x21,#8]

>  4a4:   a94153f3        ldp     x19, x20, [sp,#16]

>  4a8:   f94013f5        ldr     x21, [sp,#32]

>  4ac:   a8c97bfd        ldp     x29, x30, [sp],#144

>  4b0:   d65f03c0        ret

>  4b4:   d503201f        nop

>

> For comparison, without KASAN __incoke_psci_fn_hvc looks like:

>

> 0000000000000280 <__invoke_psci_fn_hvc>:

>  280:   d10103ff        sub     sp, sp, #0x40

>  284:   d2800007        mov     x7, #0x0                        // #0

>  288:   d2800006        mov     x6, #0x0                        // #0

>  28c:   d2800005        mov     x5, #0x0                        // #0

>  290:   a9017bfd        stp     x29, x30, [sp,#16]

>  294:   910043fd        add     x29, sp, #0x10

>  298:   910043a4        add     x4, x29, #0x10

>  29c:   f90003e4        str     x4, [sp]

>  2a0:   d2800004        mov     x4, #0x0                        // #0

>  2a4:   94000000        bl      0 <arm_smccc_hvc>

>  2a8:   910003bf        mov     sp, x29

>  2ac:   f9400ba0        ldr     x0, [x29,#16]

>  2b0:   a8c37bfd        ldp     x29, x30, [sp],#48

>  2b4:   d65f03c0        ret

>

> I also tried using __attribute__((no_sanitize_address)) directly, in

> case there was some header issue, but that doesn't seem to be the case.

>

> I'm using the Linaro 15.08 AArch64 GCC 5.1. Is anyone else able to

> confirm whether they see the same? Does the same happen for x86?

>


I am seeing the same problem with  GCC 5.2.1. Replacing the attribute with

__attribute__((optimize("-fno-sanitize=address")))

works, but appears to affect the whole object file, not just the
function to which it is attached.

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
Mark Rutland Feb. 18, 2016, 11:15 a.m. UTC | #4
On Thu, Feb 18, 2016 at 11:22:24AM +0300, Andrey Ryabinin wrote:
> 

> On 02/17/2016 10:16 PM, Mark Rutland wrote:

> > Looking at the assembly, functions seem to get instrumented regardless

> > of the __no_sanitize_address annotation. The assembly of

> > __invoke_psci_fn_{smc,hvc} look identical, even if one has the

> > annotation and one does not.

> > 

> > In the case below, it looks like __invoke_psci_fn_hvc is storing to the

> > shadow area even though it's anotated with __no_sanitize_address.  Note

> > that the adrp symbol resolution is bogus; psci_to_linux_errno happens to

> > be at offset 0 in the as-yet unlinked psci.o object.

> > 

> 

> ...

> > I also tried using __attribute__((no_sanitize_address)) directly, in

> > case there was some header issue, but that doesn't seem to be the case.

> > 

> > I'm using the Linaro 15.08 AArch64 GCC 5.1. Is anyone else able to

> > confirm whether they see the same? Does the same happen for x86?

>

> Confirming, this happens on every GCC I have (including x86).

> It seems that 'no_sanitize_address' in gcc removes only memory access checks

> but it doesn't remove stack redzones.

> I think this is wrong, e.g. clang removes instrumentation completely. I'll submit a bug.


Ok.

Unless there's some clever trickery that we can employ, the above
renders the Linux __no_sanitize_address annotation useless for this
style of code.

We should certianly call that out in the commentary in
include/linux/compiler-gcc.h.

> But we need fix this in kernel.

> I see two options here:

>  * completely disable instrumentation for drivers/firmware/psci.c


This is somewhat overkill, and we'd also have to disable instrumentation
for arch/arm64/kernel/psci.c (for psci_suspend_finisher).

I would like to have instrumentation for everything we can safely
instrument.

This is probably the least worst option, though.

>  * get back to assembly implementation


We'd also have to convert psci_suspend_finisher and psci_cpu_suspend,
the latter being generic code. That goes against the consolidation we
were aiming for.

Mark.

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
Mark Rutland Feb. 18, 2016, 11:34 a.m. UTC | #5
On Thu, Feb 18, 2016 at 12:38:09PM +0300, Andrey Ryabinin wrote:
> 

> 

> On 02/18/2016 11:22 AM, Andrey Ryabinin wrote:

> 

> > I see two options here:

> >  * completely disable instrumentation for drivers/firmware/psci.c

> >  * get back to assembly implementation

> 

> One more option is to allocate struct arm_smccc_res on stack of arm_smccc_[hvc, smc](), and return res.a0

> from arm_smccc_[hvc,smc]().


In general ARM SMCCC calls can return multiple values, and there are
callers that may care (even if they're not here just yet).

So we can't change the arm_smccc_{smc,hvc} prototypes, and adding
another asm function is somewhat self-defeating (an asm caller
of arm_smccc_* is more complex and slower than a direct SMC/HVC).

> So it will look like this:

> 

> asmlinkage unsigned long arm_smccc_hvc(unsigned long a0, unsigned long a1,

> 			unsigned long a2, unsigned long a3, unsigned long a4,

> 			unsigned long a5, unsigned long a6, unsigned long a7);

> 

> 

> static unsigned long __invoke_psci_fn_hvc(unsigned long function_id,

> 			unsigned long arg0, unsigned long arg1,

> 			unsigned long arg2)

> {

> 	return arm_smccc_hvc(function_id, arg0, arg1, arg2, 0, 0, 0, 0);

> }


While this looks like it might work today, it's going to be _extremely_
fragile -- other instrumentation might cause stack allocation and hence
shadow dirtying.

I'm not keen on this.

Thanks,
Mark.

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
Mark Rutland Feb. 18, 2016, 11:38 a.m. UTC | #6
On Thu, Feb 18, 2016 at 09:39:38AM +0000, Lorenzo Pieralisi wrote:
> On Thu, Feb 18, 2016 at 11:22:24AM +0300, Andrey Ryabinin wrote:

> 

> [...]

> 

> > > I also tried using __attribute__((no_sanitize_address)) directly, in

> > > case there was some header issue, but that doesn't seem to be the case.

> > > 

> > > I'm using the Linaro 15.08 AArch64 GCC 5.1. Is anyone else able to

> > > confirm whether they see the same? Does the same happen for x86?

> > > 

> > 

> > Confirming, this happens on every GCC I have (including x86).

> > It seems that 'no_sanitize_address' in gcc removes only memory access checks

> > but it doesn't remove stack redzones.

> > I think this is wrong, e.g. clang removes instrumentation completely. I'll submit a bug.

> > 

> > But we need fix this in kernel.

> > I see two options here:

> >  * completely disable instrumentation for drivers/firmware/psci.c

> 

> We have to have a way to disable instrumentation for functions that

> are used to call into FW and return via different code paths.

> 

> >  * get back to assembly implementation

> 

> No, we are certainly not reverting the SMCCC work because Kasan adds

> instrumentation to C functions, that's not even an option.

> 

> Is it possible at all to implement a function to remove instrumentation

> for a chunk of memory (ie resetting the shadow memory to a clean slate

> for a range of stack addresses) ?


In mm/kasan/kasan.c (which is uninstrumented) there is:

void kasan_unpoison_shadow(const void *address, size_t size)

Mark.

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
Mark Rutland Feb. 18, 2016, 12:08 p.m. UTC | #7
On Thu, Feb 18, 2016 at 02:46:30PM +0300, Andrey Ryabinin wrote:
> 

> On 02/18/2016 02:15 PM, Mark Rutland wrote:

> > On Thu, Feb 18, 2016 at 11:22:24AM +0300, Andrey Ryabinin wrote:

> >> I see two options here:

> >>  * completely disable instrumentation for drivers/firmware/psci.c

> > 

> > This is somewhat overkill, and we'd also have to disable instrumentation

> > for arch/arm64/kernel/psci.c (for psci_suspend_finisher).

> > 

> > I would like to have instrumentation for everything we can safely

> > instrument.

> > 

> > This is probably the least worst option, though.

> > 

> >>  * get back to assembly implementation

> > 

> > We'd also have to convert psci_suspend_finisher and psci_cpu_suspend,

> > the latter being generic code. That goes against the consolidation we

> > were aiming for.

> > 

> 

> Yup, I missed these two.

> In that case the only way is to manually unpoison stack.


I'm prototyping this now.

Mark.

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

Patch

diff --git a/arch/arm64/kernel/psci.c b/arch/arm64/kernel/psci.c
index f67f35b..8324ce8 100644
--- a/arch/arm64/kernel/psci.c
+++ b/arch/arm64/kernel/psci.c
@@ -32,12 +32,16 @@ 
 
 static DEFINE_PER_CPU_READ_MOSTLY(u32 *, psci_power_state);
 
+static phys_addr_t cpu_resume_phys;
+
 static int __maybe_unused cpu_psci_cpu_init_idle(unsigned int cpu)
 {
 	int i, ret, count = 0;
 	u32 *psci_states;
 	struct device_node *state_node, *cpu_node;
 
+	cpu_resume_phys = virt_to_phys(cpu_resume);
+
 	cpu_node = of_get_cpu_node(cpu, NULL);
 	if (!cpu_node)
 		return -ENODEV;
@@ -178,12 +182,10 @@  static int cpu_psci_cpu_kill(unsigned int cpu)
 }
 #endif
 
-static int psci_suspend_finisher(unsigned long index)
+__no_sanitize_address
+static int psci_suspend_finisher(unsigned long state)
 {
-	u32 *state = __this_cpu_read(psci_power_state);
-
-	return psci_ops.cpu_suspend(state[index - 1],
-				    virt_to_phys(cpu_resume));
+	return psci_ops.cpu_suspend(state, cpu_resume_phys);
 }
 
 static int __maybe_unused cpu_psci_cpu_suspend(unsigned long index)
@@ -200,7 +202,7 @@  static int __maybe_unused cpu_psci_cpu_suspend(unsigned long index)
 	if (!psci_power_state_loses_context(state[index - 1]))
 		ret = psci_ops.cpu_suspend(state[index - 1], 0);
 	else
-		ret = cpu_suspend(index, psci_suspend_finisher);
+		ret = cpu_suspend(state[index - 1], psci_suspend_finisher);
 
 	return ret;
 }
diff --git a/drivers/firmware/psci.c b/drivers/firmware/psci.c
index f25cd79..e4e8dc1 100644
--- a/drivers/firmware/psci.c
+++ b/drivers/firmware/psci.c
@@ -106,6 +106,7 @@  bool psci_power_state_is_valid(u32 state)
 	return !(state & ~valid_mask);
 }
 
+__no_sanitize_address
 static unsigned long __invoke_psci_fn_hvc(unsigned long function_id,
 			unsigned long arg0, unsigned long arg1,
 			unsigned long arg2)
@@ -116,6 +117,7 @@  static unsigned long __invoke_psci_fn_hvc(unsigned long function_id,
 	return res.a0;
 }
 
+__no_sanitize_address
 static unsigned long __invoke_psci_fn_smc(unsigned long function_id,
 			unsigned long arg0, unsigned long arg1,
 			unsigned long arg2)
@@ -148,6 +150,7 @@  static u32 psci_get_version(void)
 	return invoke_psci_fn(PSCI_0_2_FN_PSCI_VERSION, 0, 0, 0);
 }
 
+__no_sanitize_address
 static int psci_cpu_suspend(u32 state, unsigned long entry_point)
 {
 	int err;