aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorbibo,mao <bibo.mao@intel.com>2006-03-26 04:38:21 -0500
committerLinus Torvalds <torvalds@g5.osdl.org>2006-03-26 11:57:04 -0500
commit2326c77017c79fd6d55c69d8a49a57a252921bcd (patch)
tree5a2cafc7452953a4d5c8a8e8eaa0ae34fe306f74
parentc6fd91f0bdcd294a0ae0ba2b2a7f7456ef4b7144 (diff)
[PATCH] kprobe handler: discard user space trap
Currently kprobe handler traps only happen in kernel space, so function kprobe_exceptions_notify should skip traps which happen in user space. This patch modifies this, and it is based on 2.6.16-rc4. Signed-off-by: bibo mao <bibo.mao@intel.com> Cc: Ananth N Mavinakayanahalli <ananth@in.ibm.com> Cc: "Keshavamurthy, Anil S" <anil.s.keshavamurthy@intel.com> Cc: <hiramatu@sdl.hitachi.co.jp> 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>
-rw-r--r--arch/i386/kernel/kprobes.c19
-rw-r--r--arch/ia64/kernel/kprobes.c3
-rw-r--r--arch/powerpc/kernel/kprobes.c3
-rw-r--r--arch/sparc64/kernel/kprobes.c3
-rw-r--r--arch/x86_64/kernel/kprobes.c3
5 files changed, 18 insertions, 13 deletions
diff --git a/arch/i386/kernel/kprobes.c b/arch/i386/kernel/kprobes.c
index acdcc640a72a..df1b346d36ff 100644
--- a/arch/i386/kernel/kprobes.c
+++ b/arch/i386/kernel/kprobes.c
@@ -203,13 +203,14 @@ static int __kprobes kprobe_handler(struct pt_regs *regs)
203{ 203{
204 struct kprobe *p; 204 struct kprobe *p;
205 int ret = 0; 205 int ret = 0;
206 kprobe_opcode_t *addr = NULL; 206 kprobe_opcode_t *addr;
207 unsigned long *lp;
208 struct kprobe_ctlblk *kcb; 207 struct kprobe_ctlblk *kcb;
209#ifdef CONFIG_PREEMPT 208#ifdef CONFIG_PREEMPT
210 unsigned pre_preempt_count = preempt_count(); 209 unsigned pre_preempt_count = preempt_count();
211#endif /* CONFIG_PREEMPT */ 210#endif /* CONFIG_PREEMPT */
212 211
212 addr = (kprobe_opcode_t *)(regs->eip - sizeof(kprobe_opcode_t));
213
213 /* 214 /*
214 * We don't want to be preempted for the entire 215 * We don't want to be preempted for the entire
215 * duration of kprobe processing 216 * duration of kprobe processing
@@ -217,17 +218,6 @@ static int __kprobes kprobe_handler(struct pt_regs *regs)
217 preempt_disable(); 218 preempt_disable();
218 kcb = get_kprobe_ctlblk(); 219 kcb = get_kprobe_ctlblk();
219 220
220 /* Check if the application is using LDT entry for its code segment and
221 * calculate the address by reading the base address from the LDT entry.
222 */
223 if ((regs->xcs & 4) && (current->mm)) {
224 lp = (unsigned long *) ((unsigned long)((regs->xcs >> 3) * 8)
225 + (char *) current->mm->context.ldt);
226 addr = (kprobe_opcode_t *) (get_desc_base(lp) + regs->eip -
227 sizeof(kprobe_opcode_t));
228 } else {
229 addr = (kprobe_opcode_t *)(regs->eip - sizeof(kprobe_opcode_t));
230 }
231 /* Check we're not actually recursing */ 221 /* Check we're not actually recursing */
232 if (kprobe_running()) { 222 if (kprobe_running()) {
233 p = get_kprobe(addr); 223 p = get_kprobe(addr);
@@ -579,6 +569,9 @@ int __kprobes kprobe_exceptions_notify(struct notifier_block *self,
579 struct die_args *args = (struct die_args *)data; 569 struct die_args *args = (struct die_args *)data;
580 int ret = NOTIFY_DONE; 570 int ret = NOTIFY_DONE;
581 571
572 if (args->regs && user_mode(args->regs))
573 return ret;
574
582 switch (val) { 575 switch (val) {
583 case DIE_INT3: 576 case DIE_INT3:
584 if (kprobe_handler(args->regs)) 577 if (kprobe_handler(args->regs))
diff --git a/arch/ia64/kernel/kprobes.c b/arch/ia64/kernel/kprobes.c
index 50ae8c7d453d..45b8479c9864 100644
--- a/arch/ia64/kernel/kprobes.c
+++ b/arch/ia64/kernel/kprobes.c
@@ -740,6 +740,9 @@ int __kprobes kprobe_exceptions_notify(struct notifier_block *self,
740 struct die_args *args = (struct die_args *)data; 740 struct die_args *args = (struct die_args *)data;
741 int ret = NOTIFY_DONE; 741 int ret = NOTIFY_DONE;
742 742
743 if (args->regs && user_mode(args->regs))
744 return ret;
745
743 switch(val) { 746 switch(val) {
744 case DIE_BREAK: 747 case DIE_BREAK:
745 /* err is break number from ia64_bad_break() */ 748 /* err is break number from ia64_bad_break() */
diff --git a/arch/powerpc/kernel/kprobes.c b/arch/powerpc/kernel/kprobes.c
index cb1fe5878e8b..aea25dd18dae 100644
--- a/arch/powerpc/kernel/kprobes.c
+++ b/arch/powerpc/kernel/kprobes.c
@@ -396,6 +396,9 @@ int __kprobes kprobe_exceptions_notify(struct notifier_block *self,
396 struct die_args *args = (struct die_args *)data; 396 struct die_args *args = (struct die_args *)data;
397 int ret = NOTIFY_DONE; 397 int ret = NOTIFY_DONE;
398 398
399 if (args->regs && user_mode(args->regs))
400 return ret;
401
399 switch (val) { 402 switch (val) {
400 case DIE_BPT: 403 case DIE_BPT:
401 if (kprobe_handler(args->regs)) 404 if (kprobe_handler(args->regs))
diff --git a/arch/sparc64/kernel/kprobes.c b/arch/sparc64/kernel/kprobes.c
index b9a9ce70e55c..d91c31870ac8 100644
--- a/arch/sparc64/kernel/kprobes.c
+++ b/arch/sparc64/kernel/kprobes.c
@@ -324,6 +324,9 @@ int __kprobes kprobe_exceptions_notify(struct notifier_block *self,
324 struct die_args *args = (struct die_args *)data; 324 struct die_args *args = (struct die_args *)data;
325 int ret = NOTIFY_DONE; 325 int ret = NOTIFY_DONE;
326 326
327 if (args->regs && user_mode(args->regs))
328 return ret;
329
327 switch (val) { 330 switch (val) {
328 case DIE_DEBUG: 331 case DIE_DEBUG:
329 if (kprobe_handler(args->regs)) 332 if (kprobe_handler(args->regs))
diff --git a/arch/x86_64/kernel/kprobes.c b/arch/x86_64/kernel/kprobes.c
index 14f0ced613b6..218e015c3195 100644
--- a/arch/x86_64/kernel/kprobes.c
+++ b/arch/x86_64/kernel/kprobes.c
@@ -601,6 +601,9 @@ int __kprobes kprobe_exceptions_notify(struct notifier_block *self,
601 struct die_args *args = (struct die_args *)data; 601 struct die_args *args = (struct die_args *)data;
602 int ret = NOTIFY_DONE; 602 int ret = NOTIFY_DONE;
603 603
604 if (args->regs && user_mode(args->regs))
605 return ret;
606
604 switch (val) { 607 switch (val) {
605 case DIE_INT3: 608 case DIE_INT3:
606 if (kprobe_handler(args->regs)) 609 if (kprobe_handler(args->regs))