| From foo@baz Thu Dec 21 09:02:40 CET 2017 |
| From: Jon Medhurst <tixy@linaro.org> |
| Date: Thu, 2 Mar 2017 13:04:09 +0000 |
| Subject: arm: kprobes: Align stack to 8-bytes in test code |
| |
| From: Jon Medhurst <tixy@linaro.org> |
| |
| |
| [ Upstream commit 974310d047f3c7788a51d10c8d255eebdb1fa857 ] |
| |
| kprobes test cases need to have a stack that is aligned to an 8-byte |
| boundary because they call other functions (and the ARM ABI mandates |
| that alignment) and because test cases include 64-bit accesses to the |
| stack. Unfortunately, GCC doesn't ensure this alignment for inline |
| assembler and for the code in question seems to always misalign it by |
| pushing just the LR register onto the stack. We therefore need to |
| explicitly perform stack alignment at the start of each test case. |
| |
| Without this fix, some test cases will generate alignment faults on |
| systems where alignment is enforced. Even if the kernel is configured to |
| handle these faults in software, triggering them is ugly. It also |
| exposes limitations in the fault handling code which doesn't cope with |
| writes to the stack. E.g. when handling this instruction |
| |
| strd r6, [sp, #-64]! |
| |
| the fault handling code will write to a stack location below the SP |
| value at the point the fault occurred, which coincides with where the |
| exception handler has pushed the saved register context. This results in |
| corruption of those registers. |
| |
| Signed-off-by: Jon Medhurst <tixy@linaro.org> |
| Signed-off-by: Sasha Levin <alexander.levin@verizon.com> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| --- |
| arch/arm/probes/kprobes/test-core.c | 11 ++++++++--- |
| 1 file changed, 8 insertions(+), 3 deletions(-) |
| |
| --- a/arch/arm/probes/kprobes/test-core.c |
| +++ b/arch/arm/probes/kprobes/test-core.c |
| @@ -976,7 +976,10 @@ static void coverage_end(void) |
| void __naked __kprobes_test_case_start(void) |
| { |
| __asm__ __volatile__ ( |
| - "stmdb sp!, {r4-r11} \n\t" |
| + "mov r2, sp \n\t" |
| + "bic r3, r2, #7 \n\t" |
| + "mov sp, r3 \n\t" |
| + "stmdb sp!, {r2-r11} \n\t" |
| "sub sp, sp, #"__stringify(TEST_MEMORY_SIZE)"\n\t" |
| "bic r0, lr, #1 @ r0 = inline data \n\t" |
| "mov r1, sp \n\t" |
| @@ -996,7 +999,8 @@ void __naked __kprobes_test_case_end_32( |
| "movne pc, r0 \n\t" |
| "mov r0, r4 \n\t" |
| "add sp, sp, #"__stringify(TEST_MEMORY_SIZE)"\n\t" |
| - "ldmia sp!, {r4-r11} \n\t" |
| + "ldmia sp!, {r2-r11} \n\t" |
| + "mov sp, r2 \n\t" |
| "mov pc, r0 \n\t" |
| ); |
| } |
| @@ -1012,7 +1016,8 @@ void __naked __kprobes_test_case_end_16( |
| "bxne r0 \n\t" |
| "mov r0, r4 \n\t" |
| "add sp, sp, #"__stringify(TEST_MEMORY_SIZE)"\n\t" |
| - "ldmia sp!, {r4-r11} \n\t" |
| + "ldmia sp!, {r2-r11} \n\t" |
| + "mov sp, r2 \n\t" |
| "bx r0 \n\t" |
| ); |
| } |