* [PATCH 0/1] uprobes: Teach handler_chain() to filter out the probed task @ 2012-12-29 17:35 Oleg Nesterov 2012-12-29 17:36 ` [PATCH 1/1] " Oleg Nesterov 0 siblings, 1 reply; 7+ messages in thread From: Oleg Nesterov @ 2012-12-29 17:35 UTC (permalink / raw) To: Ingo Molnar, Peter Zijlstra, Srikar Dronamraju Cc: Ananth N Mavinakayanahalli, Anton Arapov, Frank Eigler, Josh Stone, Suzuki K. Poulose, linux-kernel Hello. On top of "uprobes: pre-filtering". Srikar, If you still disagree and prefer to use ->filter() in handler_chain() please argue. Note that unapply_uprobe() added by this patch can be generalized to implement uprobe_apply(consumer, mm, is_register). Oleg. ^ permalink raw reply [flat|nested] 7+ messages in thread
* [PATCH 1/1] uprobes: Teach handler_chain() to filter out the probed task 2012-12-29 17:35 [PATCH 0/1] uprobes: Teach handler_chain() to filter out the probed task Oleg Nesterov @ 2012-12-29 17:36 ` Oleg Nesterov 2013-01-08 11:18 ` Srikar Dronamraju 2013-01-10 5:35 ` Srikar Dronamraju 0 siblings, 2 replies; 7+ messages in thread From: Oleg Nesterov @ 2012-12-29 17:36 UTC (permalink / raw) To: Ingo Molnar, Peter Zijlstra, Srikar Dronamraju Cc: Ananth N Mavinakayanahalli, Anton Arapov, Frank Eigler, Josh Stone, Suzuki K. Poulose, linux-kernel Currrently the are 2 problems with pre-filtering: 1. It is not possible to add/remove a task (mm) after uprobe_register() 2. A forked child inherits all breakpoints and uprobe_consumer can not control this. This patch does the first step to improve the filtering. handler_chain() removes the breakpoints installed by this uprobe from current->mm if all handlers return UPROBE_HANDLER_REMOVE. Note that handler_chain() relies on ->register_rwsem to avoid the race with uprobe_register/unregister which can add/del a consumer, or even remove and then insert the new uprobe at the same address. Perhaps we will add uprobe_apply_mm(uprobe, mm, is_register) and teach copy_mm() to do filter(UPROBE_FILTER_FORK), but I think this change makes sense anyway. Note: instead of checking the retcode from uc->handler, we could add uc->filter(UPROBE_FILTER_BPHIT). But I think this is not optimal to call 2 hooks in a row. This buys nothing, and if handler/filter do something nontrivial they will probably do the same work twice. Signed-off-by: Oleg Nesterov <oleg@redhat.com> --- include/linux/uprobes.h | 3 ++ kernel/events/uprobes.c | 58 ++++++++++++++++++++++++++++++++++++++-------- 2 files changed, 51 insertions(+), 10 deletions(-) diff --git a/include/linux/uprobes.h b/include/linux/uprobes.h index c2df693..95d0002 100644 --- a/include/linux/uprobes.h +++ b/include/linux/uprobes.h @@ -35,6 +35,9 @@ struct inode; # include <asm/uprobes.h> #endif +#define UPROBE_HANDLER_REMOVE 1 +#define UPROBE_HANDLER_MASK 1 + enum uprobe_filter_ctx { UPROBE_FILTER_REGISTER, UPROBE_FILTER_UNREGISTER, diff --git a/kernel/events/uprobes.c b/kernel/events/uprobes.c index e2ebb6f..59b6e97 100644 --- a/kernel/events/uprobes.c +++ b/kernel/events/uprobes.c @@ -440,16 +440,6 @@ static struct uprobe *alloc_uprobe(struct inode *inode, loff_t offset) return uprobe; } -static void handler_chain(struct uprobe *uprobe, struct pt_regs *regs) -{ - struct uprobe_consumer *uc; - - down_read(&uprobe->register_rwsem); - for (uc = uprobe->consumers; uc; uc = uc->next) - uc->handler(uc, regs); - up_read(&uprobe->register_rwsem); -} - static void consumer_add(struct uprobe *uprobe, struct uprobe_consumer *uc) { down_write(&uprobe->consumer_rwsem); @@ -882,6 +872,33 @@ void uprobe_unregister(struct inode *inode, loff_t offset, struct uprobe_consume put_uprobe(uprobe); } +static int unapply_uprobe(struct uprobe *uprobe, struct mm_struct *mm) +{ + struct vm_area_struct *vma; + int err = 0; + + down_read(&mm->mmap_sem); + for (vma = mm->mmap; vma; vma = vma->vm_next) { + unsigned long vaddr; + loff_t offset; + + if (!valid_vma(vma, false) || + vma->vm_file->f_mapping->host != uprobe->inode) + continue; + + offset = (loff_t)vma->vm_pgoff << PAGE_SHIFT; + if (uprobe->offset < offset || + uprobe->offset >= offset + vma->vm_end - vma->vm_start) + continue; + + vaddr = offset_to_vaddr(vma, uprobe->offset); + err |= remove_breakpoint(uprobe, mm, vaddr); + } + up_read(&mm->mmap_sem); + + return err; +} + static struct rb_node * find_node_in_range(struct inode *inode, loff_t min, loff_t max) { @@ -1435,6 +1452,27 @@ static struct uprobe *find_active_uprobe(unsigned long bp_vaddr, int *is_swbp) return uprobe; } +static void handler_chain(struct uprobe *uprobe, struct pt_regs *regs) +{ + struct uprobe_consumer *uc; + int remove = UPROBE_HANDLER_REMOVE; + + down_read(&uprobe->register_rwsem); + for (uc = uprobe->consumers; uc; uc = uc->next) { + int rc = uc->handler(uc, regs); + + WARN(rc & ~UPROBE_HANDLER_MASK, + "bad rc=0x%x from %pf()\n", rc, uc->handler); + remove &= rc; + } + + if (remove && uprobe->consumers) { + WARN_ON(!uprobe_is_active(uprobe)); + unapply_uprobe(uprobe, current->mm); + } + up_read(&uprobe->register_rwsem); +} + /* * Run handler and ask thread to singlestep. * Ensure all non-fatal signals cannot interrupt thread while it singlesteps. -- 1.5.5.1 ^ permalink raw reply related [flat|nested] 7+ messages in thread
* Re: [PATCH 1/1] uprobes: Teach handler_chain() to filter out the probed task 2012-12-29 17:36 ` [PATCH 1/1] " Oleg Nesterov @ 2013-01-08 11:18 ` Srikar Dronamraju 2013-01-08 19:00 ` Oleg Nesterov 2013-01-10 5:35 ` Srikar Dronamraju 1 sibling, 1 reply; 7+ messages in thread From: Srikar Dronamraju @ 2013-01-08 11:18 UTC (permalink / raw) To: Oleg Nesterov Cc: Ingo Molnar, Peter Zijlstra, Ananth N Mavinakayanahalli, Anton Arapov, Frank Eigler, Josh Stone, Suzuki K. Poulose, linux-kernel * Oleg Nesterov <oleg@redhat.com> [2012-12-29 18:36:14]: > Currrently the are 2 problems with pre-filtering: > > 1. It is not possible to add/remove a task (mm) after uprobe_register() > > 2. A forked child inherits all breakpoints and uprobe_consumer can not > control this. > > This patch does the first step to improve the filtering. handler_chain() > removes the breakpoints installed by this uprobe from current->mm if all > handlers return UPROBE_HANDLER_REMOVE. > I am thinking of tid based filter, If let say a tracer is just interested in a particular thread of a process, should such a hanlder always return 0. In general, does this mean if the handler is not interested for this particular task, but not sure if other tasks in the same process could be interested, then such a handler should always return 0? If yes, should we document it (either in handler_chain() or near uprobe_consumer definition) > Note that handler_chain() relies on ->register_rwsem to avoid the race > with uprobe_register/unregister which can add/del a consumer, or even > remove and then insert the new uprobe at the same address. > > Perhaps we will add uprobe_apply_mm(uprobe, mm, is_register) and teach > copy_mm() to do filter(UPROBE_FILTER_FORK), but I think this change makes > sense anyway. > > Note: instead of checking the retcode from uc->handler, we could add > uc->filter(UPROBE_FILTER_BPHIT). But I think this is not optimal to > call 2 hooks in a row. This buys nothing, and if handler/filter do > something nontrivial they will probably do the same work twice. I was for having the filter called explicitly. But I am okay with it being called internally by the handler. My only small concern was - Given that we have an explicit filter, handlers (or folks writing handlers can misunderstand and miss filtering assuming that handlers would be called after filtering. VG > Signed-off-by: Oleg Nesterov <oleg@redhat.com> > --- > include/linux/uprobes.h | 3 ++ > kernel/events/uprobes.c | 58 ++++++++++++++++++++++++++++++++++++++-------- > 2 files changed, 51 insertions(+), 10 deletions(-) > > diff --git a/include/linux/uprobes.h b/include/linux/uprobes.h > index c2df693..95d0002 100644 > --- a/include/linux/uprobes.h > +++ b/include/linux/uprobes.h > @@ -35,6 +35,9 @@ struct inode; > # include <asm/uprobes.h> > #endif > > +#define UPROBE_HANDLER_REMOVE 1 > +#define UPROBE_HANDLER_MASK 1 > + > enum uprobe_filter_ctx { > UPROBE_FILTER_REGISTER, > UPROBE_FILTER_UNREGISTER, > diff --git a/kernel/events/uprobes.c b/kernel/events/uprobes.c > index e2ebb6f..59b6e97 100644 > --- a/kernel/events/uprobes.c > +++ b/kernel/events/uprobes.c > @@ -440,16 +440,6 @@ static struct uprobe *alloc_uprobe(struct inode *inode, loff_t offset) > return uprobe; > } > > -static void handler_chain(struct uprobe *uprobe, struct pt_regs *regs) > -{ > - struct uprobe_consumer *uc; > - > - down_read(&uprobe->register_rwsem); > - for (uc = uprobe->consumers; uc; uc = uc->next) > - uc->handler(uc, regs); > - up_read(&uprobe->register_rwsem); > -} > - > static void consumer_add(struct uprobe *uprobe, struct uprobe_consumer *uc) > { > down_write(&uprobe->consumer_rwsem); > @@ -882,6 +872,33 @@ void uprobe_unregister(struct inode *inode, loff_t offset, struct uprobe_consume > put_uprobe(uprobe); > } > > +static int unapply_uprobe(struct uprobe *uprobe, struct mm_struct *mm) > +{ > + struct vm_area_struct *vma; > + int err = 0; > + > + down_read(&mm->mmap_sem); > + for (vma = mm->mmap; vma; vma = vma->vm_next) { > + unsigned long vaddr; > + loff_t offset; > + > + if (!valid_vma(vma, false) || > + vma->vm_file->f_mapping->host != uprobe->inode) > + continue; > + > + offset = (loff_t)vma->vm_pgoff << PAGE_SHIFT; > + if (uprobe->offset < offset || > + uprobe->offset >= offset + vma->vm_end - vma->vm_start) > + continue; > + > + vaddr = offset_to_vaddr(vma, uprobe->offset); > + err |= remove_breakpoint(uprobe, mm, vaddr); > + } > + up_read(&mm->mmap_sem); > + > + return err; > +} > + > static struct rb_node * > find_node_in_range(struct inode *inode, loff_t min, loff_t max) > { > @@ -1435,6 +1452,27 @@ static struct uprobe *find_active_uprobe(unsigned long bp_vaddr, int *is_swbp) > return uprobe; > } > > +static void handler_chain(struct uprobe *uprobe, struct pt_regs *regs) > +{ > + struct uprobe_consumer *uc; > + int remove = UPROBE_HANDLER_REMOVE; > + > + down_read(&uprobe->register_rwsem); > + for (uc = uprobe->consumers; uc; uc = uc->next) { > + int rc = uc->handler(uc, regs); > + > + WARN(rc & ~UPROBE_HANDLER_MASK, > + "bad rc=0x%x from %pf()\n", rc, uc->handler); Is this warning required? > + remove &= rc; > + } > + > + if (remove && uprobe->consumers) { > + WARN_ON(!uprobe_is_active(uprobe)); > + unapply_uprobe(uprobe, current->mm); > + } > + up_read(&uprobe->register_rwsem); > +} > + The rest looks good. -- Thanks and Regards Srikar ^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [PATCH 1/1] uprobes: Teach handler_chain() to filter out the probed task 2013-01-08 11:18 ` Srikar Dronamraju @ 2013-01-08 19:00 ` Oleg Nesterov 2013-01-09 17:39 ` Srikar Dronamraju 0 siblings, 1 reply; 7+ messages in thread From: Oleg Nesterov @ 2013-01-08 19:00 UTC (permalink / raw) To: Srikar Dronamraju Cc: Ingo Molnar, Peter Zijlstra, Ananth N Mavinakayanahalli, Anton Arapov, Frank Eigler, Josh Stone, Suzuki K. Poulose, linux-kernel On 01/08, Srikar Dronamraju wrote: > > * Oleg Nesterov <oleg@redhat.com> [2012-12-29 18:36:14]: > > > This patch does the first step to improve the filtering. handler_chain() > > removes the breakpoints installed by this uprobe from current->mm if all > > handlers return UPROBE_HANDLER_REMOVE. > > > > I am thinking of tid based filter, If let say a tracer is just > interested in a particular thread of a process, should such a hanlder > always return 0. In this case ->handler() should return current->mm == PROBED_THEAD->mm ? 0 : UPROBE_HANDLER_REMOVE > In general, does this mean if the handler is not interested for this > particular task, but not sure if other tasks in the same process could > be interested, then such a handler should always return 0? Probably yes. Obviously it should return UPROBE_HANDLER_REMOVE only if it knows for sure that current can't share ->mm with the "interesting" task. Because, whatever we do, remove_breakpoint() affects ->mm, not task_struct. Our goal is eliminate do_int3(), not to skip uc->handler() call. > If yes, should we document it (either in handler_chain() or > near uprobe_consumer definition) Oh yes, I do agree. We need to add some documentation. I'll try to do this in a separate patch (although I would be happy to see the patch from someone else ;). > > Note: instead of checking the retcode from uc->handler, we could add > > uc->filter(UPROBE_FILTER_BPHIT). But I think this is not optimal to > > call 2 hooks in a row. This buys nothing, and if handler/filter do > > something nontrivial they will probably do the same work twice. > > I was for having the filter called explicitly. But I am okay with it > being called internally by the handler. OK, thanks, > My only small concern was > > - Given that we have an explicit filter, handlers (or folks writing > handlers can misunderstand and miss filtering assuming that handlers > would be called after filtering. Do you mean that they can assume that uc->filter(mm) should be called at least once before uc->handler() with the same current->mm ? They shouldn't in any case. To remind, we can optimize filter_chain() for example and avoid the potentially costly uc->filter() call. Say, we can detect/remember the fact that at least one consumre has ->filter == NULL. OTOH, UPROBE_HANDLER_REMOVE is not really pre-filtering (although I think it helps to make the things better). It is more like uprobe_unapply_mm() which (perhaps) we need as well. But doing uprobe_unapply_mm() from uc->handler is a) deadlockable and b) not optimal because it has to consult other consumers. Anyway I agree, the folks writing handlers should understand what do they do ;) and this needs some documentation. > > +static void handler_chain(struct uprobe *uprobe, struct pt_regs *regs) > > +{ > > + struct uprobe_consumer *uc; > > + int remove = UPROBE_HANDLER_REMOVE; > > + > > + down_read(&uprobe->register_rwsem); > > + for (uc = uprobe->consumers; uc; uc = uc->next) { > > + int rc = uc->handler(uc, regs); > > + > > + WARN(rc & ~UPROBE_HANDLER_MASK, > > + "bad rc=0x%x from %pf()\n", rc, uc->handler); > > Is this warning required? Of course this is not strictly needed, just to catch the simple mistakes. I can remove it. Oleg. ^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [PATCH 1/1] uprobes: Teach handler_chain() to filter out the probed task 2013-01-08 19:00 ` Oleg Nesterov @ 2013-01-09 17:39 ` Srikar Dronamraju 2013-01-09 18:13 ` Oleg Nesterov 0 siblings, 1 reply; 7+ messages in thread From: Srikar Dronamraju @ 2013-01-09 17:39 UTC (permalink / raw) To: Oleg Nesterov Cc: Ingo Molnar, Peter Zijlstra, Ananth N Mavinakayanahalli, Anton Arapov, Frank Eigler, Josh Stone, Suzuki K. Poulose, linux-kernel * Oleg Nesterov <oleg@redhat.com> [2013-01-08 20:00:18]: > On 01/08, Srikar Dronamraju wrote: > > > > * Oleg Nesterov <oleg@redhat.com> [2012-12-29 18:36:14]: > > > > > This patch does the first step to improve the filtering. handler_chain() > > > removes the breakpoints installed by this uprobe from current->mm if all > > > handlers return UPROBE_HANDLER_REMOVE. > > > > > > > I am thinking of tid based filter, If let say a tracer is just > > interested in a particular thread of a process, should such a hanlder > > always return 0. > > In this case ->handler() should return > > current->mm == PROBED_THEAD->mm ? 0 : UPROBE_HANDLER_REMOVE > > > In general, does this mean if the handler is not interested for this > > particular task, but not sure if other tasks in the same process could > > be interested, then such a handler should always return 0? > > Probably yes. Obviously it should return UPROBE_HANDLER_REMOVE only if > it knows for sure that current can't share ->mm with the "interesting" > task. > okay, then looks good. > Because, whatever we do, remove_breakpoint() affects ->mm, not task_struct. > Our goal is eliminate do_int3(), not to skip uc->handler() call. > > > If yes, should we document it (either in handler_chain() or > > near uprobe_consumer definition) > > Oh yes, I do agree. We need to add some documentation. Okay > I'll try to do > this in a separate patch (although I would be happy to see the patch > from someone else ;). > > > > Note: instead of checking the retcode from uc->handler, we could add > > > uc->filter(UPROBE_FILTER_BPHIT). But I think this is not optimal to > > > call 2 hooks in a row. This buys nothing, and if handler/filter do > > > something nontrivial they will probably do the same work twice. > > > > I was for having the filter called explicitly. But I am okay with it > > being called internally by the handler. > > OK, thanks, > > > My only small concern was > > > > - Given that we have an explicit filter, handlers (or folks writing > > handlers can misunderstand and miss filtering assuming that handlers > > would be called after filtering. > > Do you mean that they can assume that uc->filter(mm) should be called at > least once before uc->handler() with the same current->mm ? > yes, thats what I think they can assume. > They shouldn't in any case. To remind, we can optimize filter_chain() > for example and avoid the potentially costly uc->filter() call. Say, > we can detect/remember the fact that at least one consumre has > ->filter == NULL. > > OTOH, UPROBE_HANDLER_REMOVE is not really pre-filtering (although I think > it helps to make the things better). It is more like uprobe_unapply_mm() > which (perhaps) we need as well. But doing uprobe_unapply_mm() from > uc->handler is a) deadlockable and b) not optimal because it has to > consult other consumers. > > Anyway I agree, the folks writing handlers should understand what do they > do ;) and this needs some documentation. If we document explicitly that filter wont be called, then this should be okay. > > > > +static void handler_chain(struct uprobe *uprobe, struct pt_regs *regs) > > > +{ > > > + struct uprobe_consumer *uc; > > > + int remove = UPROBE_HANDLER_REMOVE; > > > + > > > + down_read(&uprobe->register_rwsem); > > > + for (uc = uprobe->consumers; uc; uc = uc->next) { > > > + int rc = uc->handler(uc, regs); > > > + > > > + WARN(rc & ~UPROBE_HANDLER_MASK, > > > + "bad rc=0x%x from %pf()\n", rc, uc->handler); > > ^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [PATCH 1/1] uprobes: Teach handler_chain() to filter out the probed task 2013-01-09 17:39 ` Srikar Dronamraju @ 2013-01-09 18:13 ` Oleg Nesterov 0 siblings, 0 replies; 7+ messages in thread From: Oleg Nesterov @ 2013-01-09 18:13 UTC (permalink / raw) To: Srikar Dronamraju Cc: Ingo Molnar, Peter Zijlstra, Ananth N Mavinakayanahalli, Anton Arapov, Frank Eigler, Josh Stone, Suzuki K. Poulose, linux-kernel On 01/09, Srikar Dronamraju wrote: > > * Oleg Nesterov <oleg@redhat.com> [2013-01-08 20:00:18]: > > > They shouldn't in any case. To remind, we can optimize filter_chain() > > for example and avoid the potentially costly uc->filter() call. Say, > > we can detect/remember the fact that at least one consumre has > > ->filter == NULL. > > > > OTOH, UPROBE_HANDLER_REMOVE is not really pre-filtering (although I think > > it helps to make the things better). It is more like uprobe_unapply_mm() > > which (perhaps) we need as well. But doing uprobe_unapply_mm() from > > uc->handler is a) deadlockable and b) not optimal because it has to > > consult other consumers. > > > > Anyway I agree, the folks writing handlers should understand what do they > > do ;) and this needs some documentation. > > If we document explicitly that filter wont be called, then this should > be okay. OK. Can I take this as your ACK? Oleg. ^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [PATCH 1/1] uprobes: Teach handler_chain() to filter out the probed task 2012-12-29 17:36 ` [PATCH 1/1] " Oleg Nesterov 2013-01-08 11:18 ` Srikar Dronamraju @ 2013-01-10 5:35 ` Srikar Dronamraju 1 sibling, 0 replies; 7+ messages in thread From: Srikar Dronamraju @ 2013-01-10 5:35 UTC (permalink / raw) To: Oleg Nesterov Cc: Ingo Molnar, Peter Zijlstra, Ananth N Mavinakayanahalli, Anton Arapov, Frank Eigler, Josh Stone, Suzuki K. Poulose, linux-kernel * Oleg Nesterov <oleg@redhat.com> [2012-12-29 18:36:14]: > Currrently the are 2 problems with pre-filtering: > > 1. It is not possible to add/remove a task (mm) after uprobe_register() > > 2. A forked child inherits all breakpoints and uprobe_consumer can not > control this. > > This patch does the first step to improve the filtering. handler_chain() > removes the breakpoints installed by this uprobe from current->mm if all > handlers return UPROBE_HANDLER_REMOVE. > > Note that handler_chain() relies on ->register_rwsem to avoid the race > with uprobe_register/unregister which can add/del a consumer, or even > remove and then insert the new uprobe at the same address. > > Perhaps we will add uprobe_apply_mm(uprobe, mm, is_register) and teach > copy_mm() to do filter(UPROBE_FILTER_FORK), but I think this change makes > sense anyway. > > Note: instead of checking the retcode from uc->handler, we could add > uc->filter(UPROBE_FILTER_BPHIT). But I think this is not optimal to > call 2 hooks in a row. This buys nothing, and if handler/filter do > something nontrivial they will probably do the same work twice. > > Signed-off-by: Oleg Nesterov <oleg@redhat.com> Acked-by: Srikar Dronamraju <srikar@linux.vnet.ibm.com> > --- > include/linux/uprobes.h | 3 ++ > kernel/events/uprobes.c | 58 ++++++++++++++++++++++++++++++++++++++-------- > 2 files changed, 51 insertions(+), 10 deletions(-) > > diff --git a/include/linux/uprobes.h b/include/linux/uprobes.h > index c2df693..95d0002 100644 > --- a/include/linux/uprobes.h > +++ b/include/linux/uprobes.h > @@ -35,6 +35,9 @@ struct inode; > # include <asm/uprobes.h> > #endif > > +#define UPROBE_HANDLER_REMOVE 1 > +#define UPROBE_HANDLER_MASK 1 > + > enum uprobe_filter_ctx { > UPROBE_FILTER_REGISTER, > UPROBE_FILTER_UNREGISTER, > diff --git a/kernel/events/uprobes.c b/kernel/events/uprobes.c > index e2ebb6f..59b6e97 100644 > --- a/kernel/events/uprobes.c > +++ b/kernel/events/uprobes.c > @@ -440,16 +440,6 @@ static struct uprobe *alloc_uprobe(struct inode *inode, loff_t offset) > return uprobe; > } > > -static void handler_chain(struct uprobe *uprobe, struct pt_regs *regs) > -{ > - struct uprobe_consumer *uc; > - > - down_read(&uprobe->register_rwsem); > - for (uc = uprobe->consumers; uc; uc = uc->next) > - uc->handler(uc, regs); > - up_read(&uprobe->register_rwsem); > -} > - > static void consumer_add(struct uprobe *uprobe, struct uprobe_consumer *uc) > { > down_write(&uprobe->consumer_rwsem); > @@ -882,6 +872,33 @@ void uprobe_unregister(struct inode *inode, loff_t offset, struct uprobe_consume > put_uprobe(uprobe); > } > > +static int unapply_uprobe(struct uprobe *uprobe, struct mm_struct *mm) > +{ > + struct vm_area_struct *vma; > + int err = 0; > + > + down_read(&mm->mmap_sem); > + for (vma = mm->mmap; vma; vma = vma->vm_next) { > + unsigned long vaddr; > + loff_t offset; > + > + if (!valid_vma(vma, false) || > + vma->vm_file->f_mapping->host != uprobe->inode) > + continue; > + > + offset = (loff_t)vma->vm_pgoff << PAGE_SHIFT; > + if (uprobe->offset < offset || > + uprobe->offset >= offset + vma->vm_end - vma->vm_start) > + continue; > + > + vaddr = offset_to_vaddr(vma, uprobe->offset); > + err |= remove_breakpoint(uprobe, mm, vaddr); > + } > + up_read(&mm->mmap_sem); > + > + return err; > +} > + > static struct rb_node * > find_node_in_range(struct inode *inode, loff_t min, loff_t max) > { > @@ -1435,6 +1452,27 @@ static struct uprobe *find_active_uprobe(unsigned long bp_vaddr, int *is_swbp) > return uprobe; > } > > +static void handler_chain(struct uprobe *uprobe, struct pt_regs *regs) > +{ > + struct uprobe_consumer *uc; > + int remove = UPROBE_HANDLER_REMOVE; > + > + down_read(&uprobe->register_rwsem); > + for (uc = uprobe->consumers; uc; uc = uc->next) { > + int rc = uc->handler(uc, regs); > + > + WARN(rc & ~UPROBE_HANDLER_MASK, > + "bad rc=0x%x from %pf()\n", rc, uc->handler); > + remove &= rc; > + } > + > + if (remove && uprobe->consumers) { > + WARN_ON(!uprobe_is_active(uprobe)); > + unapply_uprobe(uprobe, current->mm); > + } > + up_read(&uprobe->register_rwsem); > +} > + > /* > * Run handler and ask thread to singlestep. > * Ensure all non-fatal signals cannot interrupt thread while it singlesteps. > -- > 1.5.5.1 > > ^ permalink raw reply [flat|nested] 7+ messages in thread
end of thread, other threads:[~2013-01-10 5:35 UTC | newest] Thread overview: 7+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2012-12-29 17:35 [PATCH 0/1] uprobes: Teach handler_chain() to filter out the probed task Oleg Nesterov 2012-12-29 17:36 ` [PATCH 1/1] " Oleg Nesterov 2013-01-08 11:18 ` Srikar Dronamraju 2013-01-08 19:00 ` Oleg Nesterov 2013-01-09 17:39 ` Srikar Dronamraju 2013-01-09 18:13 ` Oleg Nesterov 2013-01-10 5:35 ` Srikar Dronamraju
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox; as well as URLs for NNTP newsgroup(s).