aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorWill Deacon <will.deacon@arm.com>2014-09-29 06:44:01 -0400
committerWill Deacon <will.deacon@arm.com>2014-11-14 05:42:15 -0500
commitd54e81f9af1d106e47ae8594903c43a80dae1a99 (patch)
treee3084f896a27a4658a718643a589169c51f0aa27
parent44b82b7700d05a52cd983799d3ecde1a976b3bed (diff)
arm64: entry: avoid writing lr explicitly for constructing return paths
Using an explicit adr instruction to set the link register to point at ret_fast_syscall/ret_to_user can defeat branch and return stack predictors. Instead, use the standard calling instructions (bl, blr) and have an unconditional branch as the following instruction. Signed-off-by: Will Deacon <will.deacon@arm.com>
-rw-r--r--arch/arm64/kernel/entry.S45
1 files changed, 25 insertions, 20 deletions
diff --git a/arch/arm64/kernel/entry.S b/arch/arm64/kernel/entry.S
index 726b910fe6ec..2cebe56d650c 100644
--- a/arch/arm64/kernel/entry.S
+++ b/arch/arm64/kernel/entry.S
@@ -455,8 +455,8 @@ el0_da:
455 bic x0, x26, #(0xff << 56) 455 bic x0, x26, #(0xff << 56)
456 mov x1, x25 456 mov x1, x25
457 mov x2, sp 457 mov x2, sp
458 adr lr, ret_to_user 458 bl do_mem_abort
459 b do_mem_abort 459 b ret_to_user
460el0_ia: 460el0_ia:
461 /* 461 /*
462 * Instruction abort handling 462 * Instruction abort handling
@@ -468,8 +468,8 @@ el0_ia:
468 mov x0, x26 468 mov x0, x26
469 orr x1, x25, #1 << 24 // use reserved ISS bit for instruction aborts 469 orr x1, x25, #1 << 24 // use reserved ISS bit for instruction aborts
470 mov x2, sp 470 mov x2, sp
471 adr lr, ret_to_user 471 bl do_mem_abort
472 b do_mem_abort 472 b ret_to_user
473el0_fpsimd_acc: 473el0_fpsimd_acc:
474 /* 474 /*
475 * Floating Point or Advanced SIMD access 475 * Floating Point or Advanced SIMD access
@@ -478,8 +478,8 @@ el0_fpsimd_acc:
478 ct_user_exit 478 ct_user_exit
479 mov x0, x25 479 mov x0, x25
480 mov x1, sp 480 mov x1, sp
481 adr lr, ret_to_user 481 bl do_fpsimd_acc
482 b do_fpsimd_acc 482 b ret_to_user
483el0_fpsimd_exc: 483el0_fpsimd_exc:
484 /* 484 /*
485 * Floating Point or Advanced SIMD exception 485 * Floating Point or Advanced SIMD exception
@@ -488,8 +488,8 @@ el0_fpsimd_exc:
488 ct_user_exit 488 ct_user_exit
489 mov x0, x25 489 mov x0, x25
490 mov x1, sp 490 mov x1, sp
491 adr lr, ret_to_user 491 bl do_fpsimd_exc
492 b do_fpsimd_exc 492 b ret_to_user
493el0_sp_pc: 493el0_sp_pc:
494 /* 494 /*
495 * Stack or PC alignment exception handling 495 * Stack or PC alignment exception handling
@@ -500,8 +500,8 @@ el0_sp_pc:
500 mov x0, x26 500 mov x0, x26
501 mov x1, x25 501 mov x1, x25
502 mov x2, sp 502 mov x2, sp
503 adr lr, ret_to_user 503 bl do_sp_pc_abort
504 b do_sp_pc_abort 504 b ret_to_user
505el0_undef: 505el0_undef:
506 /* 506 /*
507 * Undefined instruction 507 * Undefined instruction
@@ -510,8 +510,8 @@ el0_undef:
510 enable_dbg_and_irq 510 enable_dbg_and_irq
511 ct_user_exit 511 ct_user_exit
512 mov x0, sp 512 mov x0, sp
513 adr lr, ret_to_user 513 bl do_undefinstr
514 b do_undefinstr 514 b ret_to_user
515el0_dbg: 515el0_dbg:
516 /* 516 /*
517 * Debug exception handling 517 * Debug exception handling
@@ -530,8 +530,8 @@ el0_inv:
530 mov x0, sp 530 mov x0, sp
531 mov x1, #BAD_SYNC 531 mov x1, #BAD_SYNC
532 mrs x2, esr_el1 532 mrs x2, esr_el1
533 adr lr, ret_to_user 533 bl bad_mode
534 b bad_mode 534 b ret_to_user
535ENDPROC(el0_sync) 535ENDPROC(el0_sync)
536 536
537 .align 6 537 .align 6
@@ -653,14 +653,15 @@ el0_svc_naked: // compat entry point
653 ldr x16, [tsk, #TI_FLAGS] // check for syscall hooks 653 ldr x16, [tsk, #TI_FLAGS] // check for syscall hooks
654 tst x16, #_TIF_SYSCALL_WORK 654 tst x16, #_TIF_SYSCALL_WORK
655 b.ne __sys_trace 655 b.ne __sys_trace
656 adr lr, ret_fast_syscall // return address
657 cmp scno, sc_nr // check upper syscall limit 656 cmp scno, sc_nr // check upper syscall limit
658 b.hs ni_sys 657 b.hs ni_sys
659 ldr x16, [stbl, scno, lsl #3] // address in the syscall table 658 ldr x16, [stbl, scno, lsl #3] // address in the syscall table
660 br x16 // call sys_* routine 659 blr x16 // call sys_* routine
660 b ret_fast_syscall
661ni_sys: 661ni_sys:
662 mov x0, sp 662 mov x0, sp
663 b do_ni_syscall 663 bl do_ni_syscall
664 b ret_fast_syscall
664ENDPROC(el0_svc) 665ENDPROC(el0_svc)
665 666
666 /* 667 /*
@@ -670,17 +671,16 @@ ENDPROC(el0_svc)
670__sys_trace: 671__sys_trace:
671 mov x0, sp 672 mov x0, sp
672 bl syscall_trace_enter 673 bl syscall_trace_enter
673 adr lr, __sys_trace_return // return address
674 uxtw scno, w0 // syscall number (possibly new) 674 uxtw scno, w0 // syscall number (possibly new)
675 mov x1, sp // pointer to regs 675 mov x1, sp // pointer to regs
676 cmp scno, sc_nr // check upper syscall limit 676 cmp scno, sc_nr // check upper syscall limit
677 b.hs ni_sys 677 b.hs __ni_sys_trace
678 ldp x0, x1, [sp] // restore the syscall args 678 ldp x0, x1, [sp] // restore the syscall args
679 ldp x2, x3, [sp, #S_X2] 679 ldp x2, x3, [sp, #S_X2]
680 ldp x4, x5, [sp, #S_X4] 680 ldp x4, x5, [sp, #S_X4]
681 ldp x6, x7, [sp, #S_X6] 681 ldp x6, x7, [sp, #S_X6]
682 ldr x16, [stbl, scno, lsl #3] // address in the syscall table 682 ldr x16, [stbl, scno, lsl #3] // address in the syscall table
683 br x16 // call sys_* routine 683 blr x16 // call sys_* routine
684 684
685__sys_trace_return: 685__sys_trace_return:
686 str x0, [sp] // save returned x0 686 str x0, [sp] // save returned x0
@@ -688,6 +688,11 @@ __sys_trace_return:
688 bl syscall_trace_exit 688 bl syscall_trace_exit
689 b ret_to_user 689 b ret_to_user
690 690
691__ni_sys_trace:
692 mov x0, sp
693 bl do_ni_syscall
694 b __sys_trace_return
695
691/* 696/*
692 * Special system call wrappers. 697 * Special system call wrappers.
693 */ 698 */