aboutsummaryrefslogtreecommitdiffstats
path: root/arch/i386
diff options
context:
space:
mode:
Diffstat (limited to 'arch/i386')
-rw-r--r--arch/i386/kernel/kprobes.c26
1 files changed, 10 insertions, 16 deletions
diff --git a/arch/i386/kernel/kprobes.c b/arch/i386/kernel/kprobes.c
index 7a59050242a7..b40614f5afe2 100644
--- a/arch/i386/kernel/kprobes.c
+++ b/arch/i386/kernel/kprobes.c
@@ -362,10 +362,10 @@ static void __kprobes resume_execution(struct kprobe *p,
362 struct pt_regs *regs, struct kprobe_ctlblk *kcb) 362 struct pt_regs *regs, struct kprobe_ctlblk *kcb)
363{ 363{
364 unsigned long *tos = (unsigned long *)&regs->esp; 364 unsigned long *tos = (unsigned long *)&regs->esp;
365 unsigned long next_eip = 0;
366 unsigned long copy_eip = (unsigned long)p->ainsn.insn; 365 unsigned long copy_eip = (unsigned long)p->ainsn.insn;
367 unsigned long orig_eip = (unsigned long)p->addr; 366 unsigned long orig_eip = (unsigned long)p->addr;
368 367
368 regs->eflags &= ~TF_MASK;
369 switch (p->ainsn.insn[0]) { 369 switch (p->ainsn.insn[0]) {
370 case 0x9c: /* pushfl */ 370 case 0x9c: /* pushfl */
371 *tos &= ~(TF_MASK | IF_MASK); 371 *tos &= ~(TF_MASK | IF_MASK);
@@ -375,9 +375,9 @@ static void __kprobes resume_execution(struct kprobe *p,
375 case 0xcb: 375 case 0xcb:
376 case 0xc2: 376 case 0xc2:
377 case 0xca: 377 case 0xca:
378 regs->eflags &= ~TF_MASK; 378 case 0xea: /* jmp absolute -- eip is correct */
379 /* eip is already adjusted, no more changes required*/ 379 /* eip is already adjusted, no more changes required */
380 return; 380 goto no_change;
381 case 0xe8: /* call relative - Fix return addr */ 381 case 0xe8: /* call relative - Fix return addr */
382 *tos = orig_eip + (*tos - copy_eip); 382 *tos = orig_eip + (*tos - copy_eip);
383 break; 383 break;
@@ -385,27 +385,21 @@ static void __kprobes resume_execution(struct kprobe *p,
385 if ((p->ainsn.insn[1] & 0x30) == 0x10) { 385 if ((p->ainsn.insn[1] & 0x30) == 0x10) {
386 /* call absolute, indirect */ 386 /* call absolute, indirect */
387 /* Fix return addr; eip is correct. */ 387 /* Fix return addr; eip is correct. */
388 next_eip = regs->eip;
389 *tos = orig_eip + (*tos - copy_eip); 388 *tos = orig_eip + (*tos - copy_eip);
389 goto no_change;
390 } else if (((p->ainsn.insn[1] & 0x31) == 0x20) || /* jmp near, absolute indirect */ 390 } else if (((p->ainsn.insn[1] & 0x31) == 0x20) || /* jmp near, absolute indirect */
391 ((p->ainsn.insn[1] & 0x31) == 0x21)) { /* jmp far, absolute indirect */ 391 ((p->ainsn.insn[1] & 0x31) == 0x21)) { /* jmp far, absolute indirect */
392 /* eip is correct. */ 392 /* eip is correct. */
393 next_eip = regs->eip; 393 goto no_change;
394 } 394 }
395 break;
396 case 0xea: /* jmp absolute -- eip is correct */
397 next_eip = regs->eip;
398 break;
399 default: 395 default:
400 break; 396 break;
401 } 397 }
402 398
403 regs->eflags &= ~TF_MASK; 399 regs->eip = orig_eip + (regs->eip - copy_eip);
404 if (next_eip) { 400
405 regs->eip = next_eip; 401no_change:
406 } else { 402 return;
407 regs->eip = orig_eip + (regs->eip - copy_eip);
408 }
409} 403}
410 404
411/* 405/*