From fb10329303b55f4b7af98237e65d72c030df13b0 Mon Sep 17 00:00:00 2001 From: kenistoj Date: Fri, 25 Jan 2008 23:55:04 +0000 Subject: [PATCH] * runtime/uprobes/uprobes.c: Within a probed process, serialize calls to access_process_vm() when populating instructions slots. Fixes an SMP bug on multithreaded apps with many active probepoints. * runtime/uprobes/uprobes.h: Ditto --- ChangeLog | 8 ++++++++ runtime/uprobes/uprobes.c | 12 +++++++++++- runtime/uprobes/uprobes.h | 7 +++++++ 3 files changed, 26 insertions(+), 1 deletion(-) diff --git a/ChangeLog b/ChangeLog index 3097675e7..4d82e9e21 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,11 @@ +2008-01-25 Jim Keniston + + * runtime/uprobes/uprobes.c: Within a probed process, serialize + calls to access_process_vm() when populating instructions + slots. Fixes an SMP bug on multithreaded apps with many + active probepoints. + * runtime/uprobes/uprobes.h: Ditto + 2008-01-25 Frank Ch. Eigler PR 5672. diff --git a/runtime/uprobes/uprobes.c b/runtime/uprobes/uprobes.c index 501c4298d..f0b72c464 100644 --- a/runtime/uprobes/uprobes.c +++ b/runtime/uprobes/uprobes.c @@ -649,6 +649,7 @@ static struct uprobe_process *uprobe_mk_process(struct task_struct *p) uproc->ssol_area.insn_area = NULL; uproc->ssol_area.initialized = 0; mutex_init(&uproc->ssol_area.setup_mutex); + /* Initialize rest of area in uprobe_init_ssol(). */ #ifdef CONFIG_UPROBES_SSOL uproc->sstep_out_of_line = 1; #else @@ -1257,6 +1258,7 @@ static noinline void uprobe_init_ssol(struct uprobe_process *uproc) area->insn_area = ERR_PTR(-ENOMEM); return; } + mutex_init(&area->populate_mutex); spin_lock_init(&area->lock); area->next_slot = 0; slot_addr = (char*) area->insn_area; @@ -1405,8 +1407,10 @@ found_slot: s->last_used = jiffies; s->state = SSOL_ASSIGNED; /* Copy the original instruction to the chosen slot. */ + mutex_lock(&area->populate_mutex); len = access_process_vm(current, (unsigned long)s->insn, ppt->insn, MAX_UINSN_BYTES, 1); + mutex_unlock(&area->populate_mutex); if (unlikely(len < MAX_UINSN_BYTES)) { up_write(&s->rwsem); printk(KERN_ERR "Failed to copy instruction at %#lx" @@ -1450,12 +1454,18 @@ static struct uprobe_ssol_slot static struct uprobe_ssol_slot *uprobe_get_insn_slot(struct uprobe_probept *ppt) { - struct uprobe_ssol_slot *slot = ppt->slot; + struct uprobe_ssol_slot *slot; +retry: + slot = ppt->slot; if (unlikely(!slot)) return uprobe_find_insn_slot(ppt); down_read(&slot->rwsem); + if (unlikely(slot != ppt->slot)) { + up_read(&slot->rwsem); + goto retry; + } if (unlikely(slot->owner != ppt)) { up_read(&slot->rwsem); return uprobe_find_insn_slot(ppt); diff --git a/runtime/uprobes/uprobes.h b/runtime/uprobes/uprobes.h index e8a065992..418518f82 100644 --- a/runtime/uprobes/uprobes.h +++ b/runtime/uprobes/uprobes.h @@ -157,6 +157,13 @@ struct uprobe_ssol_area { /* lock held while finding a free slot */ spinlock_t lock; + /* + * We currently use access_process_vm() to populate instruction + * slots. Calls must be serialized because access_process_vm() + * isn't thread-safe. + */ + struct mutex populate_mutex; + /* Next slot to steal */ int next_slot; -- 2.43.5