diff options
author | Oleg Nesterov <oleg@redhat.com> | 2014-04-24 13:21:38 -0400 |
---|---|---|
committer | Oleg Nesterov <oleg@redhat.com> | 2014-04-30 13:10:38 -0400 |
commit | 2b82cadffc4154a25c25d88a63c7fb3397cda9d6 (patch) | |
tree | 05f8ea13caaf1fdd84adf154d0bd33b63cb27220 /arch | |
parent | 78d9af4cd375880a574327210eb9dab572618364 (diff) |
uprobes/x86: Introduce push_ret_address()
Extract the "push return address" code from branch_emulate_op() into
the new simple helper, push_ret_address(). It will have more users.
Signed-off-by: Oleg Nesterov <oleg@redhat.com>
Diffstat (limited to 'arch')
-rw-r--r-- | arch/x86/kernel/uprobes.c | 15 |
1 files changed, 12 insertions, 3 deletions
diff --git a/arch/x86/kernel/uprobes.c b/arch/x86/kernel/uprobes.c index a8e1d7e47001..df75913acfc0 100644 --- a/arch/x86/kernel/uprobes.c +++ b/arch/x86/kernel/uprobes.c | |||
@@ -407,6 +407,17 @@ static int default_pre_xol_op(struct arch_uprobe *auprobe, struct pt_regs *regs) | |||
407 | return 0; | 407 | return 0; |
408 | } | 408 | } |
409 | 409 | ||
410 | static int push_ret_address(struct pt_regs *regs, unsigned long ip) | ||
411 | { | ||
412 | unsigned long new_sp = regs->sp - sizeof_long(); | ||
413 | |||
414 | if (copy_to_user((void __user *)new_sp, &ip, sizeof_long())) | ||
415 | return -EFAULT; | ||
416 | |||
417 | regs->sp = new_sp; | ||
418 | return 0; | ||
419 | } | ||
420 | |||
410 | /* | 421 | /* |
411 | * Adjust the return address pushed by a call insn executed out of line. | 422 | * Adjust the return address pushed by a call insn executed out of line. |
412 | */ | 423 | */ |
@@ -517,7 +528,6 @@ static bool branch_emulate_op(struct arch_uprobe *auprobe, struct pt_regs *regs) | |||
517 | unsigned long offs = (long)auprobe->branch.offs; | 528 | unsigned long offs = (long)auprobe->branch.offs; |
518 | 529 | ||
519 | if (branch_is_call(auprobe)) { | 530 | if (branch_is_call(auprobe)) { |
520 | unsigned long new_sp = regs->sp - sizeof_long(); | ||
521 | /* | 531 | /* |
522 | * If it fails we execute this (mangled, see the comment in | 532 | * If it fails we execute this (mangled, see the comment in |
523 | * branch_clear_offset) insn out-of-line. In the likely case | 533 | * branch_clear_offset) insn out-of-line. In the likely case |
@@ -527,9 +537,8 @@ static bool branch_emulate_op(struct arch_uprobe *auprobe, struct pt_regs *regs) | |||
527 | * | 537 | * |
528 | * But there is corner case, see the comment in ->post_xol(). | 538 | * But there is corner case, see the comment in ->post_xol(). |
529 | */ | 539 | */ |
530 | if (copy_to_user((void __user *)new_sp, &new_ip, sizeof_long())) | 540 | if (push_ret_address(regs, new_ip)) |
531 | return false; | 541 | return false; |
532 | regs->sp = new_sp; | ||
533 | } else if (!check_jmp_cond(auprobe, regs)) { | 542 | } else if (!check_jmp_cond(auprobe, regs)) { |
534 | offs = 0; | 543 | offs = 0; |
535 | } | 544 | } |