aboutsummaryrefslogtreecommitdiffstats
path: root/arch
diff options
context:
space:
mode:
authorPrasanna S. Panchamukhi <prasanna@in.ibm.com>2005-01-11 01:45:42 -0800
committerLinus Torvalds <torvalds@ppc970.osdl.org>2005-01-11 01:45:42 -0800
commitf00d7730bcf29e8aed70608ec4182f02e6608b52 (patch)
treebbbcee6a6e4f83f82fef130d776b41814e73e023 /arch
parent840fed6be1038ea2b56b24dd9565e78013a7b138 (diff)
downloadhistory-f00d7730bcf29e8aed70608ec4182f02e6608b52.tar.gz
[PATCH] kprobes: dont steal interrupts from vm86
The address used by the kprobes handler was not correct if the application was using LDT entries for code segment. This patch fixes the above problem by calculating the address using base address of the current code segment. Also this patch removes the inline prefix of kprobe_handler() . Signed-off-by: Prasanna S Panchamukhi <prasanna@in.ibm.com> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Diffstat (limited to 'arch')
-rw-r--r--arch/i386/kernel/kprobes.c19
1 files changed, 16 insertions, 3 deletions
diff --git a/arch/i386/kernel/kprobes.c b/arch/i386/kernel/kprobes.c
index b9eb1a95bb53d9..1879a89d00acaf 100644
--- a/arch/i386/kernel/kprobes.c
+++ b/arch/i386/kernel/kprobes.c
@@ -86,15 +86,28 @@ static inline void prepare_singlestep(struct kprobe *p, struct pt_regs *regs)
* Interrupts are disabled on entry as trap3 is an interrupt gate and they
* remain disabled thorough out this function.
*/
-static inline int kprobe_handler(struct pt_regs *regs)
+static int kprobe_handler(struct pt_regs *regs)
{
struct kprobe *p;
int ret = 0;
- u8 *addr = (u8 *) (regs->eip - 1);
+ kprobe_opcode_t *addr = NULL;
+ unsigned long *lp;
/* We're in an interrupt, but this is clear and BUG()-safe. */
preempt_disable();
-
+ /* Check if the application is using LDT entry for its code segment and
+ * calculate the address by reading the base address from the LDT entry.
+ */
+ if ((regs->xcs & 4) && (current->mm)) {
+ lp = (unsigned long *) ((unsigned long)((regs->xcs >> 3) * 8)
+ + (char *) current->mm->context.ldt);
+ addr = (kprobe_opcode_t *) ((((*lp) >> 16 & 0x0000ffff)
+ | (*(lp +1) & 0xff000000)
+ | ((*(lp +1) << 16) & 0x00ff0000))
+ + regs->eip - sizeof(kprobe_opcode_t));
+ } else {
+ addr = (kprobe_opcode_t *)(regs->eip - sizeof(kprobe_opcode_t));
+ }
/* Check we're not actually recursing */
if (kprobe_running()) {
/* We *are* holding lock here, so this is safe.