Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1755964AbbFBKuV (ORCPT ); Tue, 2 Jun 2015 06:50:21 -0400 Received: from bombadil.infradead.org ([198.137.202.9]:35756 "EHLO bombadil.infradead.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1754598AbbFBKuR (ORCPT ); Tue, 2 Jun 2015 06:50:17 -0400 Date: Tue, 2 Jun 2015 12:50:13 +0200 From: Peter Zijlstra To: Jerome Marchand Cc: Ingo Molnar , linux-kernel@vger.kernel.org Subject: Re: [PATCH] fix a race between /proc/lock_stat and module unloading Message-ID: <20150602105013.GS3644@twins.programming.kicks-ass.net> References: <1432903635-27272-1-git-send-email-jmarchan@redhat.com> <20150602093043.GY19282@twins.programming.kicks-ass.net> <556D7D45.3040207@redhat.com> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: <556D7D45.3040207@redhat.com> User-Agent: Mutt/1.5.21 (2012-12-30) Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Length: 2698 Lines: 84 On Tue, Jun 02, 2015 at 11:54:13AM +0200, Jerome Marchand wrote: > > I guess I jumped to conclusion here and my explanation is wrong. However > there is still a bug which occurs when the kernel tries to access > class->name is seq_stats: > > [ 43.533732] BUG: unable to handle kernel paging request at > ffffffffa03181ce > [ 43.534006] IP: [] strnlen+0x9/0x50 Does something like so cure things? --- kernel/locking/lockdep.c | 3 ++- kernel/locking/lockdep_proc.c | 22 +++++++++++++++++----- 2 files changed, 19 insertions(+), 6 deletions(-) diff --git a/kernel/locking/lockdep.c b/kernel/locking/lockdep.c index a0831e1b99f4..50ed2685f937 100644 --- a/kernel/locking/lockdep.c +++ b/kernel/locking/lockdep.c @@ -3900,7 +3900,8 @@ static void zap_class(struct lock_class *class) list_del_rcu(&class->hash_entry); list_del_rcu(&class->lock_entry); - class->key = NULL; + WRITE_ONCE(class->key, NULL); + WRITE_ONCE(class->name, NULL); } static inline int within(const void *addr, void *start, unsigned long size) diff --git a/kernel/locking/lockdep_proc.c b/kernel/locking/lockdep_proc.c index ef43ac4bafb5..03946779eacc 100644 --- a/kernel/locking/lockdep_proc.c +++ b/kernel/locking/lockdep_proc.c @@ -426,10 +426,12 @@ static void seq_lock_time(struct seq_file *m, struct lock_time *lt) static void seq_stats(struct seq_file *m, struct lock_stat_data *data) { - char name[39]; - struct lock_class *class; + struct lockdep_subclass_key *ckey; struct lock_class_stats *stats; + struct lock_class *class; int i, namelen; + char name[39]; + char *cname; class = data->class; stats = &data->stats; @@ -440,15 +442,25 @@ static void seq_stats(struct seq_file *m, struct lock_stat_data *data) if (class->subclass) namelen -= 2; - if (!class->name) { + rcu_read_lock_sched(); + cname = rcu_dereference_sched(class->name); + ckey = rcu_dereference_sched(class->key); + + if (!cname && !ckey) { + rcu_read_unlock_sched(); + return; + + } else if (!cname) { char str[KSYM_NAME_LEN]; const char *key_name; - key_name = __get_key_name(class->key, str); + key_name = __get_key_name(ckey, str); snprintf(name, namelen, "%s", key_name); } else { - snprintf(name, namelen, "%s", class->name); + snprintf(name, namelen, "%s", cname); } + rcu_read_unlock_sched(); + namelen = strlen(name); if (class->name_version > 1) { snprintf(name+namelen, 3, "#%d", class->name_version); -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/