Messages in this thread | | | Date | Wed, 10 Nov 2004 21:53:00 +0300 | From | Stas Sergeev <> | Subject | Re: [patch] kprobes: dont steal interrupts from vm86 |
| |
Hi.
Prasanna S Panchamukhi wrote: >> With kprobes enabled, vm86 doesn't feel >> good. The problem is that kprobes steal >> the interrupts (mainly int3 I think) from >> it for no good reason. > If the int3 is not registered through kprobes, > kprobes handler does not handle it and it falls through the > normal int3 handler AFAIK. I was considering this, but I convinced myself that checking the VM flag is good in any case, because, as I presume, you never need the interrupts from v86. Or do you? If there is a bug in kprobes, it would be good to fix either, but I just think it will not make my patch completely useless.
> Could you please provide a test case to show that kprobes > steals the interrupts. Sure, attached. But it is not perfect: on the patched kernel it passes the test, but on the unpatched one (2.6.9), it just Oopses the kernel without printing any reasonable diagnostic. Because of the Oops, I can't demonstrate the interrupt theft right away, but I hope the test-case for the Oops in kprobe_exceptions_notify() may also be interesting for you.
#include <stdio.h> #include <string.h> #include <inttypes.h> #include <unistd.h> #include <sys/mman.h>
#include <linux/unistd.h> #include <asm/vm86.h>
_syscall2(int, vm86, int, func, struct vm86plus_struct *, v86)
static inline void set_bit(uint8_t *a, unsigned int bit) { a[bit / 8] |= (1 << (bit % 8)); }
static inline uint8_t *seg_to_linear(unsigned int seg, unsigned int reg) { return (uint8_t *)((seg << 4) + (reg & 0xffff)); }
int main() { uint8_t *vm86_mem; int ret, seg, arg, insn; struct vm86plus_struct ctx; struct vm86_regs *r;
vm86_mem = mmap((void *)0x00000000, 0x110000, PROT_WRITE | PROT_READ | PROT_EXEC, MAP_FIXED | MAP_ANON | MAP_PRIVATE, -1, 0); if (vm86_mem == MAP_FAILED) { perror("mmap"); return 1; }
memset(&ctx, 0, sizeof(ctx)); /* init basic registers */ r = &ctx.regs; r->eip = 0x100; r->esp = 0xfffe; seg = 256; r->cs = seg; r->ss = seg; r->ds = seg; r->es = seg; r->fs = seg; r->gs = seg; r->eflags = VIF_MASK;
/* put return code */ set_bit((uint8_t *)&ctx.int_revectored, 3); *seg_to_linear(r->cs, r->eip) = 0xcc; /* int3 */ *seg_to_linear(r->cs, r->eip + 1) = 0xf4; /* hlt */
do_vm86: ret = vm86(VM86_ENTER, &ctx); arg = VM86_ARG(ret); insn = *seg_to_linear(r->cs, r->eip); switch(VM86_TYPE(ret)) { case VM86_INTx: printf("vm86: INT 0x%x\n", VM86_ARG(ret)); break; case VM86_STI: case VM86_SIGNAL: /* a signal came, we just ignore that */ goto do_vm86; break; case VM86_TRAP: if (arg == 3) printf("vm86: Trap 3 - All OK\n"); else printf("Unknown trap %#x\n", arg); break; case VM86_UNKNOWN: if (insn == 0xf4) printf("vm86: HLT, test failed\n"); else printf("vm86: unknown result, insn=%#x\n", insn); default: fprintf(stderr, "unhandled vm86 return code (0x%x)\n", ret); } return 0; }
| |