* [PATCH v2 0/3] A few uprobe fixes
@ 2017-09-13 20:27 Naveen N. Rao
2017-09-13 20:28 ` [PATCH v2 1/3] kernel/uprobes: Warn if unable to install breakpoint Naveen N. Rao
` (2 more replies)
0 siblings, 3 replies; 8+ messages in thread
From: Naveen N. Rao @ 2017-09-13 20:27 UTC (permalink / raw)
To: Ingo Molnar
Cc: Oleg Nesterov, Srikar Dronamraju, Anton Blanchard,
Michael Ellerman, Ananth N Mavinakayanahalli, linux-kernel
The first patch adds a warning if we are unable to install a uprobe
breakpoint and is unchanged from the previous posting at:
https://www.mail-archive.com/linuxppc-dev@lists.ozlabs.org/msg123290.html
The second patch just rate limits the uprobe warnings and is new in this
series.
The third patch fixes how we check for an active uprobe -- we need to
consider if we were actually successful in installing the breakpoint.
This patch is new in this series as well.
- Naveen
Naveen N. Rao (3):
kernel/uprobes: Warn if unable to install breakpoint
kernel/uprobes: Ratelimit messages
kernel/uprobes: Fix check for active uprobe
kernel/events/uprobes.c | 28 +++++++++++++++++++++-------
1 file changed, 21 insertions(+), 7 deletions(-)
--
2.14.1
^ permalink raw reply [flat|nested] 8+ messages in thread* [PATCH v2 1/3] kernel/uprobes: Warn if unable to install breakpoint 2017-09-13 20:27 [PATCH v2 0/3] A few uprobe fixes Naveen N. Rao @ 2017-09-13 20:28 ` Naveen N. Rao 2017-09-15 15:53 ` Oleg Nesterov 2017-09-13 20:28 ` [PATCH v2 2/3] kernel/uprobes: Ratelimit messages Naveen N. Rao 2017-09-13 20:28 ` [PATCH v2 3/3] kernel/uprobes: Fix check for active uprobe Naveen N. Rao 2 siblings, 1 reply; 8+ messages in thread From: Naveen N. Rao @ 2017-09-13 20:28 UTC (permalink / raw) To: Ingo Molnar Cc: Oleg Nesterov, Srikar Dronamraju, Anton Blanchard, Michael Ellerman, Ananth N Mavinakayanahalli, linux-kernel When we try to install a uprobe breakpoint in uprobe_mmap(), we ignore all errors encountered in the process per this comment at the top of the function: /* * Called from mmap_region/vma_adjust with mm->mmap_sem acquired. * * Currently we ignore all errors and always return 0, the callers * can't handle the failure anyway. */ However, this is very confusing for users since no probe hits are recorded nor is an error logged in dmesg. Fix this by logging an error in dmesg so that users can discover that there was an issue with the uprobe. To facilitate use of uprobe_warn(), we move that function to the top of the file. With this patch, we see a message similar to this in dmesg: [ 201.449213] uprobe: uprobe_t:9740 failed to setup probe at 0x95c (-524) Reported-by: Anton Blanchard <anton@samba.org> Signed-off-by: Naveen N. Rao <naveen.n.rao@linux.vnet.ibm.com> --- kernel/events/uprobes.c | 21 ++++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) diff --git a/kernel/events/uprobes.c b/kernel/events/uprobes.c index 267f6ef91d97..4af1acff9cc3 100644 --- a/kernel/events/uprobes.c +++ b/kernel/events/uprobes.c @@ -112,6 +112,12 @@ struct xol_area { unsigned long vaddr; /* Page(s) of instruction slots */ }; +static void uprobe_warn(struct task_struct *t, const char *msg) +{ + pr_warn("uprobe: %s:%d failed to %s\n", + current->comm, current->pid, msg); +} + /* * valid_vma: Verify if the specified vma is an executable vma * Relax restrictions while unregistering: vm_flags might have @@ -1087,7 +1093,14 @@ int uprobe_mmap(struct vm_area_struct *vma) if (!fatal_signal_pending(current) && filter_chain(uprobe, UPROBE_FILTER_MMAP, vma->vm_mm)) { unsigned long vaddr = offset_to_vaddr(vma, uprobe->offset); - install_breakpoint(uprobe, vma->vm_mm, vma, vaddr); + int ret = install_breakpoint(uprobe, vma->vm_mm, vma, vaddr); + if (ret) { + char msg[64]; + snprintf(msg, sizeof(msg), + "setup probe at 0x%llx (%d)", + uprobe->offset, ret); + uprobe_warn(current, (const char *)msg); + } } put_uprobe(uprobe); } @@ -1468,12 +1481,6 @@ static int dup_utask(struct task_struct *t, struct uprobe_task *o_utask) return 0; } -static void uprobe_warn(struct task_struct *t, const char *msg) -{ - pr_warn("uprobe: %s:%d failed to %s\n", - current->comm, current->pid, msg); -} - static void dup_xol_work(struct callback_head *work) { if (current->flags & PF_EXITING) -- 2.14.1 ^ permalink raw reply related [flat|nested] 8+ messages in thread
* Re: [PATCH v2 1/3] kernel/uprobes: Warn if unable to install breakpoint 2017-09-13 20:28 ` [PATCH v2 1/3] kernel/uprobes: Warn if unable to install breakpoint Naveen N. Rao @ 2017-09-15 15:53 ` Oleg Nesterov 2017-09-16 11:46 ` Naveen N. Rao 0 siblings, 1 reply; 8+ messages in thread From: Oleg Nesterov @ 2017-09-15 15:53 UTC (permalink / raw) To: Naveen N. Rao Cc: Ingo Molnar, Srikar Dronamraju, Anton Blanchard, Michael Ellerman, Ananth N Mavinakayanahalli, linux-kernel On 09/14, Naveen N. Rao wrote: > > +static void uprobe_warn(struct task_struct *t, const char *msg) > +{ > + pr_warn("uprobe: %s:%d failed to %s\n", > + current->comm, current->pid, msg); > +} > + > /* > * valid_vma: Verify if the specified vma is an executable vma > * Relax restrictions while unregistering: vm_flags might have > @@ -1087,7 +1093,14 @@ int uprobe_mmap(struct vm_area_struct *vma) > if (!fatal_signal_pending(current) && > filter_chain(uprobe, UPROBE_FILTER_MMAP, vma->vm_mm)) { > unsigned long vaddr = offset_to_vaddr(vma, uprobe->offset); > - install_breakpoint(uprobe, vma->vm_mm, vma, vaddr); > + int ret = install_breakpoint(uprobe, vma->vm_mm, vma, vaddr); > + if (ret) { > + char msg[64]; > + snprintf(msg, sizeof(msg), > + "setup probe at 0x%llx (%d)", > + uprobe->offset, ret); > + uprobe_warn(current, (const char *)msg); Agreed, but... this is cosmetic, but I don't really like this snprintf(). I won't insist too much, but wouldn't it better to turn uprobe_warn() into uprobe_warn(struct task_struct *t, char *fmt, ...) ? Oleg. ^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH v2 1/3] kernel/uprobes: Warn if unable to install breakpoint 2017-09-15 15:53 ` Oleg Nesterov @ 2017-09-16 11:46 ` Naveen N. Rao 0 siblings, 0 replies; 8+ messages in thread From: Naveen N. Rao @ 2017-09-16 11:46 UTC (permalink / raw) To: Oleg Nesterov Cc: Ingo Molnar, Srikar Dronamraju, Anton Blanchard, Michael Ellerman, Ananth N Mavinakayanahalli, linux-kernel On 2017/09/15 05:53PM, Oleg Nesterov wrote: > On 09/14, Naveen N. Rao wrote: > > > > +static void uprobe_warn(struct task_struct *t, const char *msg) > > +{ > > + pr_warn("uprobe: %s:%d failed to %s\n", > > + current->comm, current->pid, msg); > > +} > > + > > /* > > * valid_vma: Verify if the specified vma is an executable vma > > * Relax restrictions while unregistering: vm_flags might have > > @@ -1087,7 +1093,14 @@ int uprobe_mmap(struct vm_area_struct *vma) > > if (!fatal_signal_pending(current) && > > filter_chain(uprobe, UPROBE_FILTER_MMAP, vma->vm_mm)) { > > unsigned long vaddr = offset_to_vaddr(vma, uprobe->offset); > > - install_breakpoint(uprobe, vma->vm_mm, vma, vaddr); > > + int ret = install_breakpoint(uprobe, vma->vm_mm, vma, vaddr); > > + if (ret) { > > + char msg[64]; > > + snprintf(msg, sizeof(msg), > > + "setup probe at 0x%llx (%d)", > > + uprobe->offset, ret); > > + uprobe_warn(current, (const char *)msg); > > Agreed, but... this is cosmetic, but I don't really like this snprintf(). > > I won't insist too much, but wouldn't it better to turn uprobe_warn() into > uprobe_warn(struct task_struct *t, char *fmt, ...) ? Good point. In fact, I think we can just use pr_fmt(). Thanks, Naveen ^ permalink raw reply [flat|nested] 8+ messages in thread
* [PATCH v2 2/3] kernel/uprobes: Ratelimit messages 2017-09-13 20:27 [PATCH v2 0/3] A few uprobe fixes Naveen N. Rao 2017-09-13 20:28 ` [PATCH v2 1/3] kernel/uprobes: Warn if unable to install breakpoint Naveen N. Rao @ 2017-09-13 20:28 ` Naveen N. Rao 2017-09-13 20:28 ` [PATCH v2 3/3] kernel/uprobes: Fix check for active uprobe Naveen N. Rao 2 siblings, 0 replies; 8+ messages in thread From: Naveen N. Rao @ 2017-09-13 20:28 UTC (permalink / raw) To: Ingo Molnar Cc: Oleg Nesterov, Srikar Dronamraju, Anton Blanchard, Michael Ellerman, Ananth N Mavinakayanahalli, linux-kernel Ratelimit warnings from uprobes so as not to flood the kernel log. Suggested-by: Michael Ellerman <mpe@ellerman.id.au> Signed-off-by: Naveen N. Rao <naveen.n.rao@linux.vnet.ibm.com> --- kernel/events/uprobes.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/kernel/events/uprobes.c b/kernel/events/uprobes.c index 4af1acff9cc3..e14eb0a6e4f3 100644 --- a/kernel/events/uprobes.c +++ b/kernel/events/uprobes.c @@ -114,8 +114,8 @@ struct xol_area { static void uprobe_warn(struct task_struct *t, const char *msg) { - pr_warn("uprobe: %s:%d failed to %s\n", - current->comm, current->pid, msg); + pr_warn_ratelimited("uprobe: %s:%d failed to %s\n", + current->comm, current->pid, msg); } /* -- 2.14.1 ^ permalink raw reply related [flat|nested] 8+ messages in thread
* [PATCH v2 3/3] kernel/uprobes: Fix check for active uprobe 2017-09-13 20:27 [PATCH v2 0/3] A few uprobe fixes Naveen N. Rao 2017-09-13 20:28 ` [PATCH v2 1/3] kernel/uprobes: Warn if unable to install breakpoint Naveen N. Rao 2017-09-13 20:28 ` [PATCH v2 2/3] kernel/uprobes: Ratelimit messages Naveen N. Rao @ 2017-09-13 20:28 ` Naveen N. Rao 2017-09-15 15:38 ` Oleg Nesterov 2 siblings, 1 reply; 8+ messages in thread From: Naveen N. Rao @ 2017-09-13 20:28 UTC (permalink / raw) To: Ingo Molnar Cc: Oleg Nesterov, Srikar Dronamraju, Anton Blanchard, Michael Ellerman, Ananth N Mavinakayanahalli, linux-kernel If we try to install a uprobe on a breakpoint instruction, we register the probe, but refuse to install it. In this case, when the breakpoint hits, we incorrectly assume that the probe hit and end up looping. Fix this by checking that the trap was actually installed in find_active_uprobe(). Reported-by: Anton Blanchard <anton@samba.org> Signed-off-by: Naveen N. Rao <naveen.n.rao@linux.vnet.ibm.com> --- kernel/events/uprobes.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/kernel/events/uprobes.c b/kernel/events/uprobes.c index e14eb0a6e4f3..599078e6a092 100644 --- a/kernel/events/uprobes.c +++ b/kernel/events/uprobes.c @@ -1752,6 +1752,13 @@ static struct uprobe *find_active_uprobe(unsigned long bp_vaddr, int *is_swbp) uprobe = find_uprobe(inode, offset); } + /* Ensure that the breakpoint was actually installed */ + if (uprobe) { + smp_rmb(); /* pairs with wmb() in prepare_uprobe() */ + if (unlikely(!test_bit(UPROBE_COPY_INSN, &uprobe->flags))) + uprobe = NULL; + } + if (!uprobe) *is_swbp = is_trap_at_addr(mm, bp_vaddr); } else { -- 2.14.1 ^ permalink raw reply related [flat|nested] 8+ messages in thread
* Re: [PATCH v2 3/3] kernel/uprobes: Fix check for active uprobe 2017-09-13 20:28 ` [PATCH v2 3/3] kernel/uprobes: Fix check for active uprobe Naveen N. Rao @ 2017-09-15 15:38 ` Oleg Nesterov 2017-09-16 11:33 ` Naveen N. Rao 0 siblings, 1 reply; 8+ messages in thread From: Oleg Nesterov @ 2017-09-15 15:38 UTC (permalink / raw) To: Naveen N. Rao Cc: Ingo Molnar, Srikar Dronamraju, Anton Blanchard, Michael Ellerman, Ananth N Mavinakayanahalli, linux-kernel Hi Naveen, I forgot almost everything about this code, but at first glance this patch needs more comments and the changelog should be updated, at least. And in any case this needs more changes iirc. On 09/14, Naveen N. Rao wrote: > > If we try to install a uprobe on a breakpoint instruction, we register the > probe, but refuse to install it. In this case, when the breakpoint hits, we > incorrectly assume that the probe hit and end up looping. This looks confusing to me... If we try to install a uprobe on a breakpoint instruction, uprobe_register() should fail and remove uprobe. The task which hits this uprobe will loop until this uprobe goes away, this is fine. But there is another case and probably this is what you mean. uprobe_register() can do nothing except insert_uprobe() if nobody mmaps this binary, and after that uprobe_mmap()->prepare_uprobe() can fail if the original isns is int3. In this case this !UPROBE_COPY_INSN uprobe won't go away, and the task can loop until it is killed or uprobe_unregister(). Right? Now. The real fix should kill UPROBE_COPY_INSN altogether and simply move prepare_uprobe() from install_breakpoint() into __uprobe_register(), before it does register_for_each_vma(). The only problem is that read_mapping_page() needs "struct file *" and nobody confirmed that read_mapping_page(data => NULL) is fine on all filesystems. I think it should be fine though, and perhaps we should finally do this change. until then we can probably make the things a bit better, but > Fix this by checking that the trap was actually installed in > find_active_uprobe(). > > Reported-by: Anton Blanchard <anton@samba.org> > Signed-off-by: Naveen N. Rao <naveen.n.rao@linux.vnet.ibm.com> > --- > kernel/events/uprobes.c | 7 +++++++ > 1 file changed, 7 insertions(+) > > diff --git a/kernel/events/uprobes.c b/kernel/events/uprobes.c > index e14eb0a6e4f3..599078e6a092 100644 > --- a/kernel/events/uprobes.c > +++ b/kernel/events/uprobes.c > @@ -1752,6 +1752,13 @@ static struct uprobe *find_active_uprobe(unsigned long bp_vaddr, int *is_swbp) > uprobe = find_uprobe(inode, offset); > } > > + /* Ensure that the breakpoint was actually installed */ > + if (uprobe) { > + smp_rmb(); /* pairs with wmb() in prepare_uprobe() */ > + if (unlikely(!test_bit(UPROBE_COPY_INSN, &uprobe->flags))) > + uprobe = NULL; > + } I need to recall how this code works... but if we add this change, shouldn't we remove another similar UPROBE_COPY_INSN check in handle_swbp() and add more comments? Oleg. ^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH v2 3/3] kernel/uprobes: Fix check for active uprobe 2017-09-15 15:38 ` Oleg Nesterov @ 2017-09-16 11:33 ` Naveen N. Rao 0 siblings, 0 replies; 8+ messages in thread From: Naveen N. Rao @ 2017-09-16 11:33 UTC (permalink / raw) To: Oleg Nesterov Cc: Ingo Molnar, Srikar Dronamraju, Anton Blanchard, Michael Ellerman, Ananth N Mavinakayanahalli, linux-kernel On 2017/09/15 05:38PM, Oleg Nesterov wrote: > Hi Naveen, Hi Oleg, > > I forgot almost everything about this code, but at first glance this patch > needs more comments and the changelog should be updated, at least. And in > any case this needs more changes iirc. Sure, thanks for the review! > > On 09/14, Naveen N. Rao wrote: > > > > If we try to install a uprobe on a breakpoint instruction, we register the > > probe, but refuse to install it. In this case, when the breakpoint hits, we > > incorrectly assume that the probe hit and end up looping. > > This looks confusing to me... > > If we try to install a uprobe on a breakpoint instruction, uprobe_register() > should fail and remove uprobe. The task which hits this uprobe will loop > until this uprobe goes away, this is fine. > > But there is another case and probably this is what you mean. uprobe_register() > can do nothing except insert_uprobe() if nobody mmaps this binary, and after that > uprobe_mmap()->prepare_uprobe() can fail if the original isns is int3. In this > case this !UPROBE_COPY_INSN uprobe won't go away, and the task can loop until > it is killed or uprobe_unregister(). > > Right? You're right -- I should have elaborated. > > > Now. The real fix should kill UPROBE_COPY_INSN altogether and simply move > prepare_uprobe() from install_breakpoint() into __uprobe_register(), before > it does register_for_each_vma(). > > The only problem is that read_mapping_page() needs "struct file *" and nobody > confirmed that read_mapping_page(data => NULL) is fine on all filesystems. > I think it should be fine though, and perhaps we should finally do this change. Sure. I will take a stab at this after these fixes. > > > until then we can probably make the things a bit better, but > > > Fix this by checking that the trap was actually installed in > > find_active_uprobe(). > > > > Reported-by: Anton Blanchard <anton@samba.org> > > Signed-off-by: Naveen N. Rao <naveen.n.rao@linux.vnet.ibm.com> > > --- > > kernel/events/uprobes.c | 7 +++++++ > > 1 file changed, 7 insertions(+) > > > > diff --git a/kernel/events/uprobes.c b/kernel/events/uprobes.c > > index e14eb0a6e4f3..599078e6a092 100644 > > --- a/kernel/events/uprobes.c > > +++ b/kernel/events/uprobes.c > > @@ -1752,6 +1752,13 @@ static struct uprobe *find_active_uprobe(unsigned long bp_vaddr, int *is_swbp) > > uprobe = find_uprobe(inode, offset); > > } > > > > + /* Ensure that the breakpoint was actually installed */ > > + if (uprobe) { > > + smp_rmb(); /* pairs with wmb() in prepare_uprobe() */ > > + if (unlikely(!test_bit(UPROBE_COPY_INSN, &uprobe->flags))) > > + uprobe = NULL; > > + } > > I need to recall how this code works... but if we add this change, shouldn't > we remove another similar UPROBE_COPY_INSN check in handle_swbp() and add more > comments? Yes, you're right. The check in handle_swbp() won't be needed anymore. I will make that change and re-spin. Thanks, Naveen ^ permalink raw reply [flat|nested] 8+ messages in thread
end of thread, other threads:[~2017-09-16 11:46 UTC | newest] Thread overview: 8+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2017-09-13 20:27 [PATCH v2 0/3] A few uprobe fixes Naveen N. Rao 2017-09-13 20:28 ` [PATCH v2 1/3] kernel/uprobes: Warn if unable to install breakpoint Naveen N. Rao 2017-09-15 15:53 ` Oleg Nesterov 2017-09-16 11:46 ` Naveen N. Rao 2017-09-13 20:28 ` [PATCH v2 2/3] kernel/uprobes: Ratelimit messages Naveen N. Rao 2017-09-13 20:28 ` [PATCH v2 3/3] kernel/uprobes: Fix check for active uprobe Naveen N. Rao 2017-09-15 15:38 ` Oleg Nesterov 2017-09-16 11:33 ` Naveen N. Rao
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox