mirror of https://gitee.com/openkylin/linux.git
x86: jprobe bugfix
jprobe for x86-64 may cause kernel page fault when the jprobe_return() is called from incorrect function. - Use jprobe_saved_regs instead getting it from stack. (Especially on x86-64, it may get incorrect data, because pt_regs can not be get by using container_of(rsp)) - Change the type of stack pointer to unsigned long *. Signed-off-by: Masami Hiramatsu <mhiramat@redhat.com> Signed-off-by: Ingo Molnar <mingo@elte.hu> Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
This commit is contained in:
parent
b4be625852
commit
29b6cd794e
|
@ -727,9 +727,7 @@ int __kprobes longjmp_break_handler(struct kprobe *p, struct pt_regs *regs)
|
||||||
|
|
||||||
if ((addr > (u8 *) jprobe_return) && (addr < (u8 *) jprobe_return_end)) {
|
if ((addr > (u8 *) jprobe_return) && (addr < (u8 *) jprobe_return_end)) {
|
||||||
if (®s->esp != kcb->jprobe_saved_esp) {
|
if (®s->esp != kcb->jprobe_saved_esp) {
|
||||||
struct pt_regs *saved_regs =
|
struct pt_regs *saved_regs = &kcb->jprobe_saved_regs;
|
||||||
container_of(kcb->jprobe_saved_esp,
|
|
||||||
struct pt_regs, esp);
|
|
||||||
printk("current esp %p does not match saved esp %p\n",
|
printk("current esp %p does not match saved esp %p\n",
|
||||||
®s->esp, kcb->jprobe_saved_esp);
|
®s->esp, kcb->jprobe_saved_esp);
|
||||||
printk("Saved registers for jprobe %p\n", jp);
|
printk("Saved registers for jprobe %p\n", jp);
|
||||||
|
|
|
@ -716,10 +716,8 @@ int __kprobes longjmp_break_handler(struct kprobe *p, struct pt_regs *regs)
|
||||||
struct jprobe *jp = container_of(p, struct jprobe, kp);
|
struct jprobe *jp = container_of(p, struct jprobe, kp);
|
||||||
|
|
||||||
if ((addr > (u8 *) jprobe_return) && (addr < (u8 *) jprobe_return_end)) {
|
if ((addr > (u8 *) jprobe_return) && (addr < (u8 *) jprobe_return_end)) {
|
||||||
if ((long *)regs->rsp != kcb->jprobe_saved_rsp) {
|
if ((unsigned long *)regs->rsp != kcb->jprobe_saved_rsp) {
|
||||||
struct pt_regs *saved_regs =
|
struct pt_regs *saved_regs = &kcb->jprobe_saved_regs;
|
||||||
container_of(kcb->jprobe_saved_rsp,
|
|
||||||
struct pt_regs, rsp);
|
|
||||||
printk("current rsp %p does not match saved rsp %p\n",
|
printk("current rsp %p does not match saved rsp %p\n",
|
||||||
(long *)regs->rsp, kcb->jprobe_saved_rsp);
|
(long *)regs->rsp, kcb->jprobe_saved_rsp);
|
||||||
printk("Saved registers for jprobe %p\n", jp);
|
printk("Saved registers for jprobe %p\n", jp);
|
||||||
|
|
|
@ -73,7 +73,7 @@ struct kprobe_ctlblk {
|
||||||
unsigned long kprobe_status;
|
unsigned long kprobe_status;
|
||||||
unsigned long kprobe_old_eflags;
|
unsigned long kprobe_old_eflags;
|
||||||
unsigned long kprobe_saved_eflags;
|
unsigned long kprobe_saved_eflags;
|
||||||
long *jprobe_saved_esp;
|
unsigned long *jprobe_saved_esp;
|
||||||
struct pt_regs jprobe_saved_regs;
|
struct pt_regs jprobe_saved_regs;
|
||||||
kprobe_opcode_t jprobes_stack[MAX_STACK_SIZE];
|
kprobe_opcode_t jprobes_stack[MAX_STACK_SIZE];
|
||||||
struct prev_kprobe prev_kprobe;
|
struct prev_kprobe prev_kprobe;
|
||||||
|
|
|
@ -66,7 +66,7 @@ struct kprobe_ctlblk {
|
||||||
unsigned long kprobe_status;
|
unsigned long kprobe_status;
|
||||||
unsigned long kprobe_old_rflags;
|
unsigned long kprobe_old_rflags;
|
||||||
unsigned long kprobe_saved_rflags;
|
unsigned long kprobe_saved_rflags;
|
||||||
long *jprobe_saved_rsp;
|
unsigned long *jprobe_saved_rsp;
|
||||||
struct pt_regs jprobe_saved_regs;
|
struct pt_regs jprobe_saved_regs;
|
||||||
kprobe_opcode_t jprobes_stack[MAX_STACK_SIZE];
|
kprobe_opcode_t jprobes_stack[MAX_STACK_SIZE];
|
||||||
struct prev_kprobe prev_kprobe;
|
struct prev_kprobe prev_kprobe;
|
||||||
|
|
Loading…
Reference in New Issue