From patchwork Wed Feb 4 03:48:08 2009 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Rusty Russell X-Patchwork-Id: 21839 X-Patchwork-Delegate: davem@davemloft.net Return-Path: X-Original-To: patchwork-incoming@ozlabs.org Delivered-To: patchwork-incoming@ozlabs.org Received: from vger.kernel.org (vger.kernel.org [209.132.176.167]) by ozlabs.org (Postfix) with ESMTP id E0E1ADDF03 for ; Wed, 4 Feb 2009 14:48:31 +1100 (EST) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1753363AbZBDDs0 (ORCPT ); Tue, 3 Feb 2009 22:48:26 -0500 Received: (majordomo@vger.kernel.org) by vger.kernel.org id S1753280AbZBDDsZ (ORCPT ); Tue, 3 Feb 2009 22:48:25 -0500 Received: from ozlabs.org ([203.10.76.45]:34618 "EHLO ozlabs.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1752998AbZBDDsY (ORCPT ); Tue, 3 Feb 2009 22:48:24 -0500 Received: from vivaldi.localnet (unknown [150.101.102.135]) (using TLSv1 with cipher DHE-RSA-AES256-SHA (256/256 bits)) (Client did not present a certificate) by ozlabs.org (Postfix) with ESMTPSA id 87AEBDDEF5; Wed, 4 Feb 2009 14:48:16 +1100 (EST) From: Rusty Russell To: Karsten Keil Subject: Re: [RFC] Suspicious bug in module refcounting Date: Wed, 4 Feb 2009 14:18:08 +1030 User-Agent: KMail/1.11.0 (Linux/2.6.27-11-generic; KDE/4.2.0; i686; ; ) Cc: linux-kernel@vger.kernel.org, Michal Hocko , richard kennedy , Dan Williams , Dmitry Torokhov , Russell King , dwmw2@infradead.org, Scott Wood , netdev@vger.kernel.org, Al Viro References: <20090203134721.GA11069@pingi.kke.suse.de> In-Reply-To: <20090203134721.GA11069@pingi.kke.suse.de> MIME-Version: 1.0 Content-Disposition: inline Message-Id: <200902041418.09630.rusty@rustcorp.com.au> Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org On Wednesday 04 February 2009 00:17:21 Karsten Keil wrote: > The refcount is a per CPU atomic variable, module_refcount() simple add > in a fully unprotected loop (not disabled irqs, not protected against > scheduling) all per cpu values. Hi Karsten, Yes, the BUG_ON() is overly aggressive. And I really hate __module_get, and it looks like most of the callers are completely bogus. The watchdog drivers use it to nail themselves in place in their open routines: this is OK, if a bit weird. We should only use __module_get() when you *can't handle* failure; otherwise you should accept that the admin did rmmod --wait and don't use the module any further. dmaengine.c seems to be taking liberties like this. AFAICT it can error out, so why not just try_module_get() always? gameport.c, serio.c and input.c increment their own refcount, but to get into those init functions someone must be holding a refcount already (ie. a module depends on this module). Ditto cyber2000fb.c, and MTD. mdio-bitbang.c should definitely use try_module_get. loop.c bumping its own refcount, Al might know why, but definitely can be try_module_get() if it's valid at all. net/socket.c can also handle failure, so that's another try_module_get. etc. > I think we should replace all unprotected __module_get() calls with > try_module_get(), or remove __module_get() completely. Agreed. We will need a "nail_module()" call for those legitimate uses (which should clear mod->exit, rather than manipulating the refcount at all). Meanwhile, I'll remove the BUG_ON for 2.6.29. Thanks, Rusty. module: remove over-zealous check in __module_get() module_refcount() isn't reliable outside stop_machine(), as demonstrated by Karsten Keil , networking can trigger it under load (an inc on one cpu and dec on another while module_refcount() is tallying can give false results, for example). Almost noone should be using __module_get, but that's another issue. Signed-off-by: Rusty Russell --- To unsubscribe from this list: send the line "unsubscribe netdev" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html diff --git a/include/linux/module.h b/include/linux/module.h --- a/include/linux/module.h +++ b/include/linux/module.h @@ -407,7 +407,6 @@ static inline void __module_get(struct m static inline void __module_get(struct module *module) { if (module) { - BUG_ON(module_refcount(module) == 0); local_inc(__module_ref_addr(module, get_cpu())); put_cpu(); }