From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1755334Ab2JFJcs (ORCPT ); Sat, 6 Oct 2012 05:32:48 -0400 Received: from e9.ny.us.ibm.com ([32.97.182.139]:42160 "EHLO e9.ny.us.ibm.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751566Ab2JFJco (ORCPT ); Sat, 6 Oct 2012 05:32:44 -0400 Date: Sat, 6 Oct 2012 15:03:11 +0530 From: Srikar Dronamraju To: Oleg Nesterov Cc: Ingo Molnar , Peter Zijlstra , Ananth N Mavinakayanahalli , Anton Arapov , Sebastian Andrzej Siewior , linux-kernel@vger.kernel.org Subject: Re: [PATCH 4/7] uprobes: Fix handle_swbp() vs unregister() + register() race Message-ID: <20121006093311.GB9145@linux.vnet.ibm.com> Reply-To: Srikar Dronamraju References: <20120930194119.GA11278@redhat.com> <20120930194211.GA11333@redhat.com> MIME-Version: 1.0 Content-Type: text/plain; charset=iso-8859-1 Content-Disposition: inline In-Reply-To: <20120930194211.GA11333@redhat.com> User-Agent: Mutt/1.5.20 (2009-06-14) x-cbid: 12100609-7182-0000-0000-000002C1FBFD Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org * Oleg Nesterov [2012-09-30 21:42:11]: > Strictly speaking this race was added by me in 56bb4cf6. However > I think that this bug is just another indication that we should > move copy_insn/uprobe_analyze_insn code from install_breakpoint() > to uprobe_register(), there are a lot of other reasons for that. > Until then, add a hack to close the race. > > A task can hit uprobe U1, but before it calls find_uprobe() this > uprobe can be unregistered *AND* another uprobe U2 can be added to > uprobes_tree at the same inode/offset. In this case handle_swbp() > will use the not-fully-initialized U2, in particular its arch.insn > for xol. > > Add the additional !UPROBE_COPY_INSN check into find_active_uprobe, > if this flag is not set we simply restart as if the new uprobe was > not inserted yet. This is not very nice, we need barriers, but we > will remove this hack when we change uprobe_register(). > > Note: with or without this patch install_breakpoint() can race with > itself, yet another reson to kill UPROBE_COPY_INSN altogether. And > even the usage of uprobe->flags is not safe. See the next patches. > > Signed-off-by: Oleg Nesterov > --- > kernel/events/uprobes.c | 11 +++++++++++ > 1 files changed, 11 insertions(+), 0 deletions(-) > > diff --git a/kernel/events/uprobes.c b/kernel/events/uprobes.c > index 6058231..a81080f 100644 > --- a/kernel/events/uprobes.c > +++ b/kernel/events/uprobes.c > @@ -596,6 +596,7 @@ install_breakpoint(struct uprobe *uprobe, struct mm_struct *mm, > BUG_ON((uprobe->offset & ~PAGE_MASK) + > UPROBE_SWBP_INSN_SIZE > PAGE_SIZE); > > + smp_wmb(); /* pairs with rmb() in find_active_uprobe() */ > uprobe->flags |= UPROBE_COPY_INSN; > } > > @@ -1391,6 +1392,16 @@ static struct uprobe *find_active_uprobe(unsigned long bp_vaddr, int *is_swbp) > if (!uprobe && test_and_clear_bit(MMF_RECALC_UPROBES, &mm->flags)) > mmf_recalc_uprobes(mm); > up_read(&mm->mmap_sem); > + /* > + * TODO: move copy_insn/etc into _register and remove this hack. > + * After we hit the bp, _unregister + _register can install the > + * new and not-yet-analyzed uprobe at the same address, restart. > + */ > + smp_rmb(); /* pairs with wmb() in install_breakpoint() */ > + if (uprobe && unlikely(!(uprobe->flags & UPROBE_COPY_INSN))) { > + uprobe = NULL; > + *is_swbp = 0; > + } > > return uprobe; > } Should we be adding this check handle_swbp() around can_skip_step()? The earliest we access arch.insn is in can_skip_step. So we give some more time for the instruction to be copied. Also it will probably be a little cleaner, (Not having to drop a uprobe reference, not having to reset is_swbp.) -- Thanks and Regards Srikar