From: Oleg Nesterov <oleg@redhat.com>
To: Ingo Molnar <mingo@elte.hu>,
Peter Zijlstra <peterz@infradead.org>,
Srikar Dronamraju <srikar@linux.vnet.ibm.com>
Cc: Ananth N Mavinakayanahalli <ananth@in.ibm.com>,
Anton Arapov <anton@redhat.com>, Frank Eigler <fche@redhat.com>,
Josh Stone <jistone@redhat.com>,
"Suzuki K. Poulose" <suzuki@in.ibm.com>,
linux-kernel@vger.kernel.org
Subject: [PATCH 2/2] uprobes: Reintroduce uprobe_consumer->filter()
Date: Fri, 28 Dec 2012 19:13:14 +0100 [thread overview]
Message-ID: <20121228181314.GA6141@redhat.com> (raw)
In-Reply-To: <20121228181252.GA6120@redhat.com>
Finally add uprobe_consumer->filter() and change consumer_filter()
to actually call this method.
Note that ->filter() accepts mm_struct, not task_struct. Because:
1. We do not have for_each_mm_user(mm, task).
2. Even if we implement for_each_mm_user(), ->filter() can
use it itself.
3. It is not clear who will actually need this interface to
do the "nontrivial" filtering.
Another argument is "enum uprobe_filter_ctx", consumer->filter() can
use it to figure out why/where it was called. For example, perhaps
we can add UPROBE_FILTER_PRE_REGISTER used by build_map_info() to
quickly "nack" the unwanted mm's. In this case consumer should know
that it is called under ->i_mmap_mutex.
See the previous discussion at http://marc.info/?t=135214229700002
Perhaps we should pass more arguments, vma/vaddr?
Note: this patch obviously can't help to filter out the child created
by fork(), this will be addressed later.
Signed-off-by: Oleg Nesterov <oleg@redhat.com>
---
include/linux/uprobes.h | 9 +++++++++
kernel/events/uprobes.c | 18 +++++++++++-------
2 files changed, 20 insertions(+), 7 deletions(-)
diff --git a/include/linux/uprobes.h b/include/linux/uprobes.h
index 83742b9..c2df693 100644
--- a/include/linux/uprobes.h
+++ b/include/linux/uprobes.h
@@ -35,8 +35,17 @@ struct inode;
# include <asm/uprobes.h>
#endif
+enum uprobe_filter_ctx {
+ UPROBE_FILTER_REGISTER,
+ UPROBE_FILTER_UNREGISTER,
+ UPROBE_FILTER_MMAP,
+};
+
struct uprobe_consumer {
int (*handler)(struct uprobe_consumer *self, struct pt_regs *regs);
+ bool (*filter)(struct uprobe_consumer *self,
+ enum uprobe_filter_ctx ctx,
+ struct mm_struct *mm);
struct uprobe_consumer *next;
};
diff --git a/kernel/events/uprobes.c b/kernel/events/uprobes.c
index 60b0a90..e2ebb6f 100644
--- a/kernel/events/uprobes.c
+++ b/kernel/events/uprobes.c
@@ -579,19 +579,21 @@ static int prepare_uprobe(struct uprobe *uprobe, struct file *file,
return ret;
}
-static inline bool consumer_filter(struct uprobe_consumer *uc)
+static inline bool consumer_filter(struct uprobe_consumer *uc,
+ enum uprobe_filter_ctx ctx, struct mm_struct *mm)
{
- return true; /* TODO: !uc->filter || uc->filter(...) */
+ return !uc->filter || uc->filter(uc, ctx, mm);
}
-static bool filter_chain(struct uprobe *uprobe)
+static bool filter_chain(struct uprobe *uprobe,
+ enum uprobe_filter_ctx ctx, struct mm_struct *mm)
{
struct uprobe_consumer *uc;
bool ret = false;
down_read(&uprobe->consumer_rwsem);
for (uc = uprobe->consumers; uc; uc = uc->next) {
- ret = consumer_filter(uc);
+ ret = consumer_filter(uc, ctx, mm);
if (ret)
break;
}
@@ -772,10 +774,12 @@ static int register_for_each_vma(struct uprobe *uprobe, bool is_register)
if (is_register) {
/* consult only the "caller", new consumer. */
- if (consumer_filter(uprobe->consumers))
+ if (consumer_filter(uprobe->consumers,
+ UPROBE_FILTER_REGISTER, mm))
err = install_breakpoint(uprobe, mm, vma, info->vaddr);
} else if (test_bit(MMF_HAS_UPROBES, &mm->flags)) {
- if (!filter_chain(uprobe))
+ if (!filter_chain(uprobe,
+ UPROBE_FILTER_UNREGISTER, mm))
err |= remove_breakpoint(uprobe, mm, info->vaddr);
}
@@ -968,7 +972,7 @@ int uprobe_mmap(struct vm_area_struct *vma)
*/
list_for_each_entry_safe(uprobe, u, &tmp_list, pending_list) {
if (!fatal_signal_pending(current) &&
- filter_chain(uprobe)) {
+ 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);
}
--
1.5.5.1
next prev parent reply other threads:[~2012-12-28 18:13 UTC|newest]
Thread overview: 5+ messages / expand[flat|nested] mbox.gz Atom feed top
2012-12-28 18:12 [PATCH 0/2] uprobes: pre-filtering Oleg Nesterov
2012-12-28 18:13 ` [PATCH 1/2] uprobes: Rationalize the usage of filter_chain() Oleg Nesterov
2013-01-03 11:56 ` Srikar Dronamraju
2012-12-28 18:13 ` Oleg Nesterov [this message]
2013-01-03 11:56 ` [PATCH 2/2] uprobes: Reintroduce uprobe_consumer->filter() Srikar Dronamraju
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20121228181314.GA6141@redhat.com \
--to=oleg@redhat.com \
--cc=ananth@in.ibm.com \
--cc=anton@redhat.com \
--cc=fche@redhat.com \
--cc=jistone@redhat.com \
--cc=linux-kernel@vger.kernel.org \
--cc=mingo@elte.hu \
--cc=peterz@infradead.org \
--cc=srikar@linux.vnet.ibm.com \
--cc=suzuki@in.ibm.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.