All of lore.kernel.org
 help / color / mirror / Atom feed
From: Rusty Russell <rusty@rustcorp.com.au>
To: Brandon Philips <brandon@ifup.org>
Cc: "Rafael J. Wysocki" <rjw@sisk.pl>,
	Linus Torvalds <torvalds@linux-foundation.org>,
	LKML <linux-kernel@vger.kernel.org>,
	Andrew Morton <akpm@linux-foundation.org>,
	Jon Masters <jonathan@jonmasters.org>,
	Tejun Heo <htejun@gmail.com>,
	Masami Hiramatsu <mhiramat@redhat.com>,
	Kay Sievers <kay.sievers@vrfy.org>
Subject: [PATCH 2/2] module: fix bne2 "gave up waiting for init of module libcrc32c"
Date: Mon, 31 May 2010 21:32:27 +0930	[thread overview]
Message-ID: <201005312132.28631.rusty@rustcorp.com.au> (raw)
In-Reply-To: <201005312131.43238.rusty@rustcorp.com.au>

Problem: it's hard to avoid an init routine stumbling over a
request_module these days.  And it's not clear it's always a bad idea:
for example, a module like kvm with dynamic dependencies on kvm-intel
or kvm-amd would be neater if it could simply request_module the right
one.

In this particular case, it's libcrc32c:

	libcrc32c_mod_init
	 crypto_alloc_shash
	  crypto_alloc_tfm
	   crypto_find_alg
	    crypto_alg_mod_lookup
	     crypto_larval_lookup
	      request_module

If another module is waiting for libcrc32c to finish initializing
(ie. bne2 depends on libcrc32c) then it does so holding the module
lock, and our request_module() can't make progress until that is
released.

Waiting without the lock isn't all that hard: we just need to pass the
-EBUSY up the call chain so we can sleep where we don't hold the lock.
Error reporting is a bit trickier: we need to copy the name of the
unfinished module before releasing the lock.

Other notes:
1) This also fixes a theoretical issue where a weak dependency would allow
   symbol version mismatches to be ignored.
2) We rename use_module to ref_module to make life easier for the only
   external user (the out-of-tree ksplice patches).

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
Cc: Brandon Philips <brandon@ifup.org>
Cc: Avi Kivity <avi@redhat.com>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Tim Abbot <tabbott@ksplice.com>
---
 kernel/module.c |   91 ++++++++++++++++++++++++++++++++++++--------------------
 1 file changed, 59 insertions(+), 32 deletions(-)

diff --git a/kernel/module.c b/kernel/module.c
--- a/kernel/module.c
+++ b/kernel/module.c
@@ -559,40 +559,33 @@ static int already_uses(struct module *a
 }
 
 /* Module a uses b: caller needs module_mutex() */
-int use_module(struct module *a, struct module *b)
+int ref_module(struct module *a, struct module *b)
 {
 	struct module_use *use;
 	int no_warn, err;
 
-	if (b == NULL || already_uses(a, b)) return 1;
+	if (b == NULL || already_uses(a, b))
+		return 0;
 
 	/* If we're interrupted or time out, we fail. */
-	if (wait_event_interruptible_timeout(
-		    module_wq, (err = strong_try_module_get(b)) != -EBUSY,
-		    30 * HZ) <= 0) {
-		printk("%s: gave up waiting for init of module %s.\n",
-		       a->name, b->name);
-		return 0;
-	}
-
-	/* If strong_try_module_get() returned a different error, we fail. */
+	err = strong_try_module_get(b);
 	if (err)
-		return 0;
+		return err;
 
 	DEBUGP("Allocating new usage for %s.\n", a->name);
 	use = kmalloc(sizeof(*use), GFP_ATOMIC);
 	if (!use) {
 		printk("%s: out of memory loading\n", a->name);
 		module_put(b);
-		return 0;
+		return -ENOMEM;
 	}
 
 	use->module_which_uses = a;
 	list_add(&use->list, &b->modules_which_use_me);
 	no_warn = sysfs_create_link(b->holders_dir, &a->mkobj.kobj, a->name);
-	return 1;
+	return 0;
 }
-EXPORT_SYMBOL_GPL(use_module);
+EXPORT_SYMBOL_GPL(ref_module);
 
 /* Clear the unload stuff of the module. */
 static void module_unload_free(struct module *mod)
@@ -888,11 +881,11 @@ static inline void module_unload_free(st
 {
 }
 
-int use_module(struct module *a, struct module *b)
+int ref_module(struct module *a, struct module *b)
 {
-	return strong_try_module_get(b) == 0;
+	return strong_try_module_get(b);
 }
-EXPORT_SYMBOL_GPL(use_module);
+EXPORT_SYMBOL_GPL(ref_module);
 
 static inline void module_unload_init(struct module *mod)
 {
@@ -1057,26 +1050,58 @@ static inline int same_magic(const char 
 static const struct kernel_symbol *resolve_symbol(Elf_Shdr *sechdrs,
 						  unsigned int versindex,
 						  const char *name,
-						  struct module *mod)
+						  struct module *mod,
+						  char ownername[])
 {
 	struct module *owner;
 	const struct kernel_symbol *sym;
 	const unsigned long *crc;
+	int err;
 
 	mutex_lock(&module_mutex);
 	sym = find_symbol(name, &owner, &crc,
 			  !(mod->taints & (1 << TAINT_PROPRIETARY_MODULE)), true);
-	/* use_module can fail due to OOM,
-	   or module initialization or unloading */
-	if (sym) {
-		if (!check_version(sechdrs, versindex, name, mod, crc, owner)
-		    || !use_module(mod, owner))
-			sym = NULL;
+	if (!sym)
+		goto unlock;
+
+	if (!check_version(sechdrs, versindex, name, mod, crc, owner)) {
+		sym = ERR_PTR(-EINVAL);
+		goto getname;
 	}
+
+	err = ref_module(mod, owner);
+	if (err) {
+		sym = ERR_PTR(err);
+		goto getname;
+	}
+
+getname:
+	/* We must make copy under the lock if we failed to get ref. */
+	strncpy(ownername, module_name(owner), MODULE_NAME_LEN);
+unlock:
 	mutex_unlock(&module_mutex);
 	return sym;
 }
 
+static const struct kernel_symbol *resolve_symbol_wait(Elf_Shdr *sechdrs,
+						       unsigned int versindex,
+						       const char *name,
+						       struct module *mod)
+{
+	const struct kernel_symbol *ksym;
+	char ownername[MODULE_NAME_LEN];
+
+	if (wait_event_interruptible_timeout(module_wq,
+			IS_ERR(ksym = resolve_symbol(sechdrs, versindex, name,
+						     mod, ownername)) &&
+			PTR_ERR(ksym) == -EBUSY,
+					     30 * HZ) <= 0) {
+		printk(KERN_WARNING "%s: gave up waiting for init of module %s.\n",
+		       mod->name, ownername);
+	}
+	return ksym;
+}
+
 /*
  * /sys/module/foo/sections stuff
  * J. Corbet <corbet@lwn.net>
@@ -1578,21 +1603,23 @@ static int simplify_symbols(Elf_Shdr *se
 			break;
 
 		case SHN_UNDEF:
-			ksym = resolve_symbol(sechdrs, versindex,
-					      strtab + sym[i].st_name, mod);
+			ksym = resolve_symbol_wait(sechdrs, versindex,
+						   strtab + sym[i].st_name,
+						   mod);
 			/* Ok if resolved.  */
-			if (ksym) {
+			if (ksym && !IS_ERR(ksym)) {
 				sym[i].st_value = ksym->value;
 				break;
 			}
 
 			/* Ok if weak.  */
-			if (ELF_ST_BIND(sym[i].st_info) == STB_WEAK)
+			if (!ksym && ELF_ST_BIND(sym[i].st_info) == STB_WEAK)
 				break;
 
-			printk(KERN_WARNING "%s: Unknown symbol %s\n",
-			       mod->name, strtab + sym[i].st_name);
-			ret = -ENOENT;
+			printk(KERN_WARNING "%s: Unknown symbol %s (err %li)\n",
+			       mod->name, strtab + sym[i].st_name,
+			       PTR_ERR(ksym));
+			ret = PTR_ERR(ksym) ?: -ENOENT;
 			break;
 
 		default:

  reply	other threads:[~2010-05-31 12:02 UTC|newest]

Thread overview: 71+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2010-05-25 21:00 [Regression] Crash in load_module() while freeing args Rafael J. Wysocki
2010-05-25 22:54 ` Rafael J. Wysocki
2010-05-25 23:47   ` Linus Torvalds
2010-05-26  8:00     ` Rusty Russell
2010-05-26 11:57       ` Rusty Russell
2010-05-26 22:56         ` Rafael J. Wysocki
2010-05-26 23:07           ` Linus Torvalds
2010-05-27  5:26           ` Rusty Russell
2010-05-27 18:46             ` Brandon Philips
2010-05-31  9:40               ` Rusty Russell
2010-05-31 12:00                 ` [PATCH 0/2] kernel/module.c locking changes Rusty Russell
2010-05-31 12:01                   ` [PATCH 1/2] module: make locking more fine-grained Rusty Russell
2010-05-31 12:02                     ` Rusty Russell [this message]
2010-05-31 16:48                       ` [PATCH 2/2] module: fix bne2 "gave up waiting for init of module libcrc32c" Andrew Morton
2010-05-31 18:19                         ` Linus Torvalds
2010-05-31 20:15                           ` Linus Torvalds
2010-05-31 20:16                             ` [PATCH 1/2] Make the module 'usage' lists be two-way Linus Torvalds
2010-05-31 20:17                               ` [PATCH 2/2] module: wait for other modules after dropping the module_mutex Linus Torvalds
2010-06-01  1:37                               ` [PATCH 1/2] Make the module 'usage' lists be two-way Rusty Russell
2010-06-01  3:42                                 ` Rusty Russell
2010-06-01  4:00                                   ` Linus Torvalds
2010-06-01  4:05                                     ` Linus Torvalds
2010-06-01  2:44                               ` Américo Wang
2010-06-01  3:51                                 ` Linus Torvalds
2010-06-01  1:57                             ` [PATCH 2/2] module: fix bne2 "gave up waiting for init of module libcrc32c" Rusty Russell
2010-06-01  3:40                               ` Linus Torvalds
2010-06-01  4:27                                 ` Linus Torvalds
2010-06-01  5:19                                 ` Rusty Russell
2010-06-02  3:15                                   ` Rusty Russell
2010-06-01  1:21                           ` Rusty Russell
2010-06-01  3:24                             ` Linus Torvalds
2010-06-01  5:22                               ` Rusty Russell
2010-06-01 14:58                                 ` Linus Torvalds
2010-06-01 17:53                                   ` Linus Torvalds
2010-06-01 23:24                                     ` Brandon Philips
2010-06-01 23:51                                       ` Linus Torvalds
2010-06-02  2:10                                         ` Brandon Philips
2010-06-02  3:03                                           ` Rusty Russell
2010-06-02  4:35                                           ` Linus Torvalds
2010-06-02  4:44                                             ` Linus Torvalds
2010-06-02  6:35                                               ` Rusty Russell
2010-06-02  7:45                                                 ` Linus Torvalds
2010-06-02  8:12                                                   ` Linus Torvalds
2010-06-02  9:07                                                     ` Rusty Russell
2010-06-02  5:52                                             ` Rusty Russell
2010-06-02  7:21                                               ` Linus Torvalds
2010-06-02 14:06                                                 ` Rusty Russell
2010-06-02 14:50                                                   ` Linus Torvalds
2010-06-03 13:06                                                     ` Rusty Russell
2010-06-02 16:53                                                   ` Brandon Philips
2010-06-02 18:01                                                   ` Linus Torvalds
2010-06-03  5:20                                                     ` Rusty Russell
2010-06-03 16:24                                                       ` Linus Torvalds
2010-06-04  1:02                                                         ` Rusty Russell
2010-06-04  1:55                                                           ` Linus Torvalds
2010-06-04  5:20                                                             ` Rusty Russell
2010-06-04 22:48                                                               ` Linus Torvalds
2010-06-05  1:49                                                                 ` Rusty Russell
2010-06-02  3:09                                   ` Rusty Russell
2010-06-02  4:32                                     ` Linus Torvalds
2010-06-02  4:56                                     ` Linus Torvalds
2010-06-02  5:52                                       ` Rusty Russell
2010-06-02  6:59                                         ` Linus Torvalds
2010-06-01  1:04                         ` Rusty Russell
2010-06-01  5:38                     ` [PATCH 1/2] module: make locking more fine-grained Américo Wang
2010-06-01  5:55                       ` Rusty Russell
2010-05-27 21:57             ` [Regression] Crash in load_module() while freeing args Rafael J. Wysocki
2010-05-31  7:54               ` Rusty Russell
2010-05-31 10:23               ` [PATCH] module: fix reference to mod->percpu after freeing module Rusty Russell
2010-05-31 10:25                 ` Tejun Heo
2010-05-26 15:41       ` [Regression] Crash in load_module() while freeing args Linus Torvalds

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=201005312132.28631.rusty@rustcorp.com.au \
    --to=rusty@rustcorp.com.au \
    --cc=akpm@linux-foundation.org \
    --cc=brandon@ifup.org \
    --cc=htejun@gmail.com \
    --cc=jonathan@jonmasters.org \
    --cc=kay.sievers@vrfy.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=mhiramat@redhat.com \
    --cc=rjw@sisk.pl \
    --cc=torvalds@linux-foundation.org \
    /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.