[kernel/f14] Backport 5336377d6225959624146629ce3fc88ee8ecda3d for RHBZ 648571

Josh Boyer jwboyer at fedoraproject.org
Tue Sep 13 20:49:04 UTC 2011


commit cf5a635e41bb1b40c45f4c68611eab0ffe3d0980
Author: Josh Boyer <jwboyer at redhat.com>
Date:   Mon Sep 12 10:59:49 2011 -0400

    Backport 5336377d6225959624146629ce3fc88ee8ecda3d for RHBZ 648571

 kernel.spec                                        |   11 +-
 ...-Fix-module_bug_list-list-corruption-race.patch |  271 ++++++++++++++++++++
 2 files changed, 281 insertions(+), 1 deletions(-)
---
diff --git a/kernel.spec b/kernel.spec
index 95ed6e0..cc12bce 100644
--- a/kernel.spec
+++ b/kernel.spec
@@ -48,7 +48,7 @@ Summary: The Linux kernel
 # reset this by hand to 1 (or to 0 and then use rpmdev-bumpspec).
 # scripts/rebase.sh should be made to do that for you, actually.
 #
-%global baserelease 96
+%global baserelease 97
 %global fedora_build %{baserelease}
 
 # base_sublevel is the kernel version we're starting with and patching
@@ -861,6 +861,9 @@ Patch14040: asix-add-USB-ID-for-Logitec-LAN-GTJ-U2A.patch
 # RHBZ #665109
 Patch14050: x86-PCI-don-t-use-native-Broadcom-CNB20LE-driver-whe.patch
 
+# RHBZ #648571
+Patch14051: modules-Fix-module_bug_list-list-corruption-race.patch
+
 %endif
 
 BuildRoot: %{_tmppath}/kernel-%{KVERREL}-root
@@ -1621,6 +1624,9 @@ ApplyPatch asix-add-USB-ID-for-Logitec-LAN-GTJ-U2A.patch
 # RHBZ #665109
 ApplyPatch x86-PCI-don-t-use-native-Broadcom-CNB20LE-driver-whe.patch
 
+# RHBZ #648571
+ApplyPatch modules-Fix-module_bug_list-list-corruption-race.patch
+
 # END OF PATCH APPLICATIONS
 
 %endif
@@ -2207,6 +2213,9 @@ fi
 # and build.
 
 %changelog
+* Mon Sep 12 2011 Josh Boyer <jwboyer at redhat.com>
+- Backport 5336377d to fix RHBZ #648571
+
 * Wed Aug 31 2011 Josh Boyer <jwboyer at redhat.com> 2.6.35.14-96
 - Add patch to fix RHBZ #665109
 
diff --git a/modules-Fix-module_bug_list-list-corruption-race.patch b/modules-Fix-module_bug_list-list-corruption-race.patch
new file mode 100644
index 0000000..ab62ae6
--- /dev/null
+++ b/modules-Fix-module_bug_list-list-corruption-race.patch
@@ -0,0 +1,271 @@
+From 9aad2d11106f9a42593ee8eb3f10bc469873a18e Mon Sep 17 00:00:00 2001
+From: Linus Torvalds <torvalds at linux-foundation.org>
+Date: Tue, 5 Oct 2010 11:29:27 -0700
+Subject: [PATCH] modules: Fix module_bug_list list corruption race
+
+With all the recent module loading cleanups, we've minimized the code
+that sits under module_mutex, fixing various deadlocks and making it
+possible to do most of the module loading in parallel.
+
+However, that whole conversion totally missed the rather obscure code
+that adds a new module to the list for BUG() handling.  That code was
+doubly obscure because (a) the code itself lives in lib/bugs.c (for
+dubious reasons) and (b) it gets called from the architecture-specific
+"module_finalize()" rather than from generic code.
+
+Calling it from arch-specific code makes no sense what-so-ever to begin
+with, and is now actively wrong since that code isn't protected by the
+module loading lock any more.
+
+So this commit moves the "module_bug_{finalize,cleanup}()" calls away
+from the arch-specific code, and into the generic code - and in the
+process protects it with the module_mutex so that the list operations
+are now safe.
+
+Future fixups:
+ - move the module list handling code into kernel/module.c where it
+   belongs.
+ - get rid of 'module_bug_list' and just use the regular list of modules
+   (called 'modules' - imagine that) that we already create and maintain
+   for other reasons.
+
+Reported-and-tested-by: Thomas Gleixner <tglx at linutronix.de>
+Cc: Rusty Russell <rusty at rustcorp.com.au>
+Cc: Adrian Bunk <bunk at kernel.org>
+Cc: Andrew Morton <akpm at linux-foundation.org>
+Cc: stable at kernel.org
+Signed-off-by: Linus Torvalds <torvalds at linux-foundation.org>
+---
+ arch/avr32/kernel/module.c   |    3 +--
+ arch/h8300/kernel/module.c   |    3 +--
+ arch/mn10300/kernel/module.c |    3 +--
+ arch/parisc/kernel/module.c  |    3 +--
+ arch/powerpc/kernel/module.c |    5 -----
+ arch/s390/kernel/module.c    |    3 +--
+ arch/sh/kernel/module.c      |    2 --
+ arch/x86/kernel/module.c     |    3 +--
+ include/linux/module.h       |    5 ++---
+ kernel/module.c              |    4 ++++
+ lib/bug.c                    |    6 ++----
+ 11 files changed, 14 insertions(+), 26 deletions(-)
+
+diff --git a/arch/avr32/kernel/module.c b/arch/avr32/kernel/module.c
+index 98f94d0..a727f54 100644
+--- a/arch/avr32/kernel/module.c
++++ b/arch/avr32/kernel/module.c
+@@ -314,10 +314,9 @@ int module_finalize(const Elf_Ehdr *hdr, const Elf_Shdr *sechdrs,
+ 	vfree(module->arch.syminfo);
+ 	module->arch.syminfo = NULL;
+ 
+-	return module_bug_finalize(hdr, sechdrs, module);
++	return 0;
+ }
+ 
+ void module_arch_cleanup(struct module *module)
+ {
+-	module_bug_cleanup(module);
+ }
+diff --git a/arch/h8300/kernel/module.c b/arch/h8300/kernel/module.c
+index 0865e29..db4953d 100644
+--- a/arch/h8300/kernel/module.c
++++ b/arch/h8300/kernel/module.c
+@@ -112,10 +112,9 @@ int module_finalize(const Elf_Ehdr *hdr,
+ 		    const Elf_Shdr *sechdrs,
+ 		    struct module *me)
+ {
+-	return module_bug_finalize(hdr, sechdrs, me);
++	return 0;
+ }
+ 
+ void module_arch_cleanup(struct module *mod)
+ {
+-	module_bug_cleanup(mod);
+ }
+diff --git a/arch/mn10300/kernel/module.c b/arch/mn10300/kernel/module.c
+index 6aea7fd..196a111 100644
+--- a/arch/mn10300/kernel/module.c
++++ b/arch/mn10300/kernel/module.c
+@@ -206,7 +206,7 @@ int module_finalize(const Elf_Ehdr *hdr,
+ 		    const Elf_Shdr *sechdrs,
+ 		    struct module *me)
+ {
+-	return module_bug_finalize(hdr, sechdrs, me);
++	return 0;
+ }
+ 
+ /*
+@@ -214,5 +214,4 @@ int module_finalize(const Elf_Ehdr *hdr,
+  */
+ void module_arch_cleanup(struct module *mod)
+ {
+-	module_bug_cleanup(mod);
+ }
+diff --git a/arch/parisc/kernel/module.c b/arch/parisc/kernel/module.c
+index 159a2b8..6e81bb5 100644
+--- a/arch/parisc/kernel/module.c
++++ b/arch/parisc/kernel/module.c
+@@ -941,11 +941,10 @@ int module_finalize(const Elf_Ehdr *hdr,
+ 	nsyms = newptr - (Elf_Sym *)symhdr->sh_addr;
+ 	DEBUGP("NEW num_symtab %lu\n", nsyms);
+ 	symhdr->sh_size = nsyms * sizeof(Elf_Sym);
+-	return module_bug_finalize(hdr, sechdrs, me);
++	return 0;
+ }
+ 
+ void module_arch_cleanup(struct module *mod)
+ {
+ 	deregister_unwind_table(mod);
+-	module_bug_cleanup(mod);
+ }
+diff --git a/arch/powerpc/kernel/module.c b/arch/powerpc/kernel/module.c
+index 477c663..4ef93ae 100644
+--- a/arch/powerpc/kernel/module.c
++++ b/arch/powerpc/kernel/module.c
+@@ -65,10 +65,6 @@ int module_finalize(const Elf_Ehdr *hdr,
+ 	const Elf_Shdr *sect;
+ 	int err;
+ 
+-	err = module_bug_finalize(hdr, sechdrs, me);
+-	if (err)
+-		return err;
+-
+ 	/* Apply feature fixups */
+ 	sect = find_section(hdr, sechdrs, "__ftr_fixup");
+ 	if (sect != NULL)
+@@ -101,5 +97,4 @@ int module_finalize(const Elf_Ehdr *hdr,
+ 
+ void module_arch_cleanup(struct module *mod)
+ {
+-	module_bug_cleanup(mod);
+ }
+diff --git a/arch/s390/kernel/module.c b/arch/s390/kernel/module.c
+index 22cfd63..f7167ee 100644
+--- a/arch/s390/kernel/module.c
++++ b/arch/s390/kernel/module.c
+@@ -407,10 +407,9 @@ int module_finalize(const Elf_Ehdr *hdr,
+ {
+ 	vfree(me->arch.syminfo);
+ 	me->arch.syminfo = NULL;
+-	return module_bug_finalize(hdr, sechdrs, me);
++	return 0;
+ }
+ 
+ void module_arch_cleanup(struct module *mod)
+ {
+-	module_bug_cleanup(mod);
+ }
+diff --git a/arch/sh/kernel/module.c b/arch/sh/kernel/module.c
+index 43adddf..ae0be69 100644
+--- a/arch/sh/kernel/module.c
++++ b/arch/sh/kernel/module.c
+@@ -149,13 +149,11 @@ int module_finalize(const Elf_Ehdr *hdr,
+ 	int ret = 0;
+ 
+ 	ret |= module_dwarf_finalize(hdr, sechdrs, me);
+-	ret |= module_bug_finalize(hdr, sechdrs, me);
+ 
+ 	return ret;
+ }
+ 
+ void module_arch_cleanup(struct module *mod)
+ {
+-	module_bug_cleanup(mod);
+ 	module_dwarf_cleanup(mod);
+ }
+diff --git a/arch/x86/kernel/module.c b/arch/x86/kernel/module.c
+index e0bc186..1c355c5 100644
+--- a/arch/x86/kernel/module.c
++++ b/arch/x86/kernel/module.c
+@@ -239,11 +239,10 @@ int module_finalize(const Elf_Ehdr *hdr,
+ 		apply_paravirt(pseg, pseg + para->sh_size);
+ 	}
+ 
+-	return module_bug_finalize(hdr, sechdrs, me);
++	return 0;
+ }
+ 
+ void module_arch_cleanup(struct module *mod)
+ {
+ 	alternatives_smp_module_del(mod);
+-	module_bug_cleanup(mod);
+ }
+diff --git a/include/linux/module.h b/include/linux/module.h
+index 8a6b9fd..aace066 100644
+--- a/include/linux/module.h
++++ b/include/linux/module.h
+@@ -686,17 +686,16 @@ extern int module_sysfs_initialized;
+ 
+ 
+ #ifdef CONFIG_GENERIC_BUG
+-int  module_bug_finalize(const Elf_Ehdr *, const Elf_Shdr *,
++void module_bug_finalize(const Elf_Ehdr *, const Elf_Shdr *,
+ 			 struct module *);
+ void module_bug_cleanup(struct module *);
+ 
+ #else	/* !CONFIG_GENERIC_BUG */
+ 
+-static inline int  module_bug_finalize(const Elf_Ehdr *hdr,
++static inline void module_bug_finalize(const Elf_Ehdr *hdr,
+ 					const Elf_Shdr *sechdrs,
+ 					struct module *mod)
+ {
+-	return 0;
+ }
+ static inline void module_bug_cleanup(struct module *mod) {}
+ #endif	/* CONFIG_GENERIC_BUG */
+diff --git a/kernel/module.c b/kernel/module.c
+index 6c56282..eca6e02 100644
+--- a/kernel/module.c
++++ b/kernel/module.c
+@@ -1533,6 +1533,7 @@ static int __unlink_module(void *_mod)
+ {
+ 	struct module *mod = _mod;
+ 	list_del(&mod->list);
++	module_bug_cleanup(mod);
+ 	return 0;
+ }
+ 
+@@ -2538,6 +2539,7 @@ static noinline struct module *load_module(void __user *umod,
+ 	if (err < 0)
+ 		goto ddebug;
+ 
++	module_bug_finalize(hdr, sechdrs, mod);
+ 	list_add_rcu(&mod->list, &modules);
+ 	mutex_unlock(&module_mutex);
+ 
+@@ -2564,6 +2566,8 @@ static noinline struct module *load_module(void __user *umod,
+ 	mutex_lock(&module_mutex);
+ 	/* Unlink carefully: kallsyms could be walking list. */
+ 	list_del_rcu(&mod->list);
++	module_bug_cleanup(mod);
++
+  ddebug:
+ 	dynamic_debug_remove(debug);
+  unlock:
+diff --git a/lib/bug.c b/lib/bug.c
+index f13daf4..c005615 100644
+--- a/lib/bug.c
++++ b/lib/bug.c
+@@ -72,8 +72,8 @@ static const struct bug_entry *module_find_bug(unsigned long bugaddr)
+ 	return NULL;
+ }
+ 
+-int module_bug_finalize(const Elf_Ehdr *hdr, const Elf_Shdr *sechdrs,
+-			struct module *mod)
++void module_bug_finalize(const Elf_Ehdr *hdr, const Elf_Shdr *sechdrs,
++			 struct module *mod)
+ {
+ 	char *secstrings;
+ 	unsigned int i;
+@@ -97,8 +97,6 @@ int module_bug_finalize(const Elf_Ehdr *hdr, const Elf_Shdr *sechdrs,
+ 	 * could potentially lead to deadlock and thus be counter-productive.
+ 	 */
+ 	list_add(&mod->bug_list, &module_bug_list);
+-
+-	return 0;
+ }
+ 
+ void module_bug_cleanup(struct module *mod)
+-- 
+1.7.6
+


More information about the scm-commits mailing list