aboutsummaryrefslogtreecommitdiffstats
path: root/arch
diff options
context:
space:
mode:
Diffstat (limited to 'arch')
-rw-r--r--arch/x86/kernel/uprobes.c15
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
410static 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 }