x86/kprobes: Verify stack frame on kretprobe

Verify the stack frame pointer on kretprobe trampoline handler,
If the stack frame pointer does not match, it skips the wrong
entry and tries to find correct one.

This can happen if user puts the kretprobe on the function
which can be used in the path of ftrace user-function call.
Such functions should not be probed, so this adds a warning
message that reports which function should be blacklisted.

Tested-by: Andrea Righi <righi.andrea@gmail.com>
Signed-off-by: Masami Hiramatsu <mhiramat@kernel.org>
Acked-by: Steven Rostedt <rostedt@goodmis.org>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: stable@vger.kernel.org
Link: http://lkml.kernel.org/r/155094059185.6137.15527904013362842072.stgit@devbox
Signed-off-by: Ingo Molnar <mingo@kernel.org>

authored by Masami Hiramatsu and committed by Ingo Molnar 3ff9c075 3fe3331b

+27
+26
arch/x86/kernel/kprobes/core.c
··· 569 569 unsigned long *sara = stack_addr(regs); 570 570 571 571 ri->ret_addr = (kprobe_opcode_t *) *sara; 572 + ri->fp = sara; 572 573 573 574 /* Replace the return addr with trampoline addr */ 574 575 *sara = (unsigned long) &kretprobe_trampoline; ··· 760 759 unsigned long flags, orig_ret_address = 0; 761 760 unsigned long trampoline_address = (unsigned long)&kretprobe_trampoline; 762 761 kprobe_opcode_t *correct_ret_addr = NULL; 762 + void *frame_pointer; 763 + bool skipped = false; 763 764 764 765 INIT_HLIST_HEAD(&empty_rp); 765 766 kretprobe_hash_lock(current, &head, &flags); 766 767 /* fixup registers */ 767 768 #ifdef CONFIG_X86_64 768 769 regs->cs = __KERNEL_CS; 770 + /* On x86-64, we use pt_regs->sp for return address holder. */ 771 + frame_pointer = &regs->sp; 769 772 #else 770 773 regs->cs = __KERNEL_CS | get_kernel_rpl(); 771 774 regs->gs = 0; 775 + /* On x86-32, we use pt_regs->flags for return address holder. */ 776 + frame_pointer = &regs->flags; 772 777 #endif 773 778 regs->ip = trampoline_address; 774 779 regs->orig_ax = ~0UL; ··· 796 789 if (ri->task != current) 797 790 /* another task is sharing our hash bucket */ 798 791 continue; 792 + /* 793 + * Return probes must be pushed on this hash list correct 794 + * order (same as return order) so that it can be poped 795 + * correctly. However, if we find it is pushed it incorrect 796 + * order, this means we find a function which should not be 797 + * probed, because the wrong order entry is pushed on the 798 + * path of processing other kretprobe itself. 799 + */ 800 + if (ri->fp != frame_pointer) { 801 + if (!skipped) 802 + pr_warn("kretprobe is stacked incorrectly. Trying to fixup.\n"); 803 + skipped = true; 804 + continue; 805 + } 799 806 800 807 orig_ret_address = (unsigned long)ri->ret_addr; 808 + if (skipped) 809 + pr_warn("%ps must be blacklisted because of incorrect kretprobe order\n", 810 + ri->rp->kp.addr); 801 811 802 812 if (orig_ret_address != trampoline_address) 803 813 /* ··· 831 807 hlist_for_each_entry_safe(ri, tmp, head, hlist) { 832 808 if (ri->task != current) 833 809 /* another task is sharing our hash bucket */ 810 + continue; 811 + if (ri->fp != frame_pointer) 834 812 continue; 835 813 836 814 orig_ret_address = (unsigned long)ri->ret_addr;
+1
include/linux/kprobes.h
··· 173 173 struct kretprobe *rp; 174 174 kprobe_opcode_t *ret_addr; 175 175 struct task_struct *task; 176 + void *fp; 176 177 char data[0]; 177 178 }; 178 179