aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/fork.c
diff options
context:
space:
mode:
authorSrikar Dronamraju <srikar@linux.vnet.ibm.com>2012-03-13 14:00:11 -0400
committerIngo Molnar <mingo@elte.hu>2012-03-14 02:41:36 -0400
commit0326f5a94ddea33fa331b2519f4172f4fb387baa (patch)
tree5485c637754a126c90852e5285842e8462d2826a /kernel/fork.c
parentef15eda98217f5183f457e7a2de8b79555ef908b (diff)
uprobes/core: Handle breakpoint and singlestep exceptions
Uprobes uses exception notifiers to get to know if a thread hit a breakpoint or a singlestep exception. When a thread hits a uprobe or is singlestepping post a uprobe hit, the uprobe exception notifier sets its TIF_UPROBE bit, which will then be checked on its return to userspace path (do_notify_resume() ->uprobe_notify_resume()), where the consumers handlers are run (in task context) based on the defined filters. Uprobe hits are thread specific and hence we need to maintain information about if a task hit a uprobe, what uprobe was hit, the slot where the original instruction was copied for xol so that it can be singlestepped with appropriate fixups. In some cases, special care is needed for instructions that are executed out of line (xol). These are architecture specific artefacts, such as handling RIP relative instructions on x86_64. Since the instruction at which the uprobe was inserted is executed out of line, architecture specific fixups are added so that the thread continues normal execution in the presence of a uprobe. Postpone the signals until we execute the probed insn. post_xol() path does a recalc_sigpending() before return to user-mode, this ensures the signal can't be lost. Uprobes relies on DIE_DEBUG notification to notify if a singlestep is complete. Adds x86 specific uprobe exception notifiers and appropriate hooks needed to determine a uprobe hit and subsequent post processing. Add requisite x86 fixups for xol for uprobes. Specific cases needing fixups include relative jumps (x86_64), calls, etc. Where possible, we check and skip singlestepping the breakpointed instructions. For now we skip single byte as well as few multibyte nop instructions. However this can be extended to other instructions too. Credits to Oleg Nesterov for suggestions/patches related to signal, breakpoint, singlestep handling code. Signed-off-by: Srikar Dronamraju <srikar@linux.vnet.ibm.com> Cc: Linus Torvalds <torvalds@linux-foundation.org> Cc: Ananth N Mavinakayanahalli <ananth@in.ibm.com> Cc: Jim Keniston <jkenisto@linux.vnet.ibm.com> Cc: Linux-mm <linux-mm@kvack.org> Cc: Oleg Nesterov <oleg@redhat.com> Cc: Andi Kleen <andi@firstfloor.org> Cc: Christoph Hellwig <hch@infradead.org> Cc: Steven Rostedt <rostedt@goodmis.org> Cc: Arnaldo Carvalho de Melo <acme@infradead.org> Cc: Masami Hiramatsu <masami.hiramatsu.pt@hitachi.com> Cc: Peter Zijlstra <peterz@infradead.org> Link: http://lkml.kernel.org/r/20120313180011.29771.89027.sendpatchset@srdronam.in.ibm.com [ Performed various cleanliness edits ] Signed-off-by: Ingo Molnar <mingo@elte.hu>
Diffstat (limited to 'kernel/fork.c')
-rw-r--r--kernel/fork.c4
1 files changed, 4 insertions, 0 deletions
diff --git a/kernel/fork.c b/kernel/fork.c
index e2cd3e2a5ae8..eb7b63334009 100644
--- a/kernel/fork.c
+++ b/kernel/fork.c
@@ -67,6 +67,7 @@
67#include <linux/oom.h> 67#include <linux/oom.h>
68#include <linux/khugepaged.h> 68#include <linux/khugepaged.h>
69#include <linux/signalfd.h> 69#include <linux/signalfd.h>
70#include <linux/uprobes.h>
70 71
71#include <asm/pgtable.h> 72#include <asm/pgtable.h>
72#include <asm/pgalloc.h> 73#include <asm/pgalloc.h>
@@ -701,6 +702,8 @@ void mm_release(struct task_struct *tsk, struct mm_struct *mm)
701 exit_pi_state_list(tsk); 702 exit_pi_state_list(tsk);
702#endif 703#endif
703 704
705 uprobe_free_utask(tsk);
706
704 /* Get rid of any cached register state */ 707 /* Get rid of any cached register state */
705 deactivate_mm(tsk, mm); 708 deactivate_mm(tsk, mm);
706 709
@@ -1295,6 +1298,7 @@ static struct task_struct *copy_process(unsigned long clone_flags,
1295 INIT_LIST_HEAD(&p->pi_state_list); 1298 INIT_LIST_HEAD(&p->pi_state_list);
1296 p->pi_state_cache = NULL; 1299 p->pi_state_cache = NULL;
1297#endif 1300#endif
1301 uprobe_copy_process(p);
1298 /* 1302 /*
1299 * sigaltstack should be cleared when sharing the same VM 1303 * sigaltstack should be cleared when sharing the same VM
1300 */ 1304 */