diff --git a/kernel.spec b/kernel.spec index 95ed6e082..cc12bced0 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 +- Backport 5336377d to fix RHBZ #648571 + * Wed Aug 31 2011 Josh Boyer 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 000000000..ab62ae6aa --- /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 +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 +Cc: Rusty Russell +Cc: Adrian Bunk +Cc: Andrew Morton +Cc: stable@kernel.org +Signed-off-by: Linus Torvalds +--- + 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 +