aboutsummaryrefslogtreecommitdiffstats
path: root/arch
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2010-10-05 14:29:27 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2010-10-05 14:29:27 -0400
commit5336377d6225959624146629ce3fc88ee8ecda3d (patch)
tree571b9db75d1ba50faa1e399509563f367fd5694f /arch
parent2f6b3aa7a563d05453c4d73ccf88191aee84333f (diff)
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@linutronix.de> Cc: Rusty Russell <rusty@rustcorp.com.au> Cc: Adrian Bunk <bunk@kernel.org> Cc: Andrew Morton <akpm@linux-foundation.org> Cc: stable@kernel.org Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'arch')
-rw-r--r--arch/avr32/kernel/module.c3
-rw-r--r--arch/h8300/kernel/module.c3
-rw-r--r--arch/mn10300/kernel/module.c3
-rw-r--r--arch/parisc/kernel/module.c3
-rw-r--r--arch/powerpc/kernel/module.c5
-rw-r--r--arch/s390/kernel/module.c3
-rw-r--r--arch/sh/kernel/module.c2
-rw-r--r--arch/x86/kernel/module.c3
8 files changed, 6 insertions, 19 deletions
diff --git a/arch/avr32/kernel/module.c b/arch/avr32/kernel/module.c
index 98f94d041d9c..a727f54d64d6 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,
314 vfree(module->arch.syminfo); 314 vfree(module->arch.syminfo);
315 module->arch.syminfo = NULL; 315 module->arch.syminfo = NULL;
316 316
317 return module_bug_finalize(hdr, sechdrs, module); 317 return 0;
318} 318}
319 319
320void module_arch_cleanup(struct module *module) 320void module_arch_cleanup(struct module *module)
321{ 321{
322 module_bug_cleanup(module);
323} 322}
diff --git a/arch/h8300/kernel/module.c b/arch/h8300/kernel/module.c
index 0865e291c20d..db4953dc4e1b 100644
--- a/arch/h8300/kernel/module.c
+++ b/arch/h8300/kernel/module.c
@@ -112,10 +112,9 @@ int module_finalize(const Elf_Ehdr *hdr,
112 const Elf_Shdr *sechdrs, 112 const Elf_Shdr *sechdrs,
113 struct module *me) 113 struct module *me)
114{ 114{
115 return module_bug_finalize(hdr, sechdrs, me); 115 return 0;
116} 116}
117 117
118void module_arch_cleanup(struct module *mod) 118void module_arch_cleanup(struct module *mod)
119{ 119{
120 module_bug_cleanup(mod);
121} 120}
diff --git a/arch/mn10300/kernel/module.c b/arch/mn10300/kernel/module.c
index 6aea7fd76993..196a111e2e29 100644
--- a/arch/mn10300/kernel/module.c
+++ b/arch/mn10300/kernel/module.c
@@ -206,7 +206,7 @@ int module_finalize(const Elf_Ehdr *hdr,
206 const Elf_Shdr *sechdrs, 206 const Elf_Shdr *sechdrs,
207 struct module *me) 207 struct module *me)
208{ 208{
209 return module_bug_finalize(hdr, sechdrs, me); 209 return 0;
210} 210}
211 211
212/* 212/*
@@ -214,5 +214,4 @@ int module_finalize(const Elf_Ehdr *hdr,
214 */ 214 */
215void module_arch_cleanup(struct module *mod) 215void module_arch_cleanup(struct module *mod)
216{ 216{
217 module_bug_cleanup(mod);
218} 217}
diff --git a/arch/parisc/kernel/module.c b/arch/parisc/kernel/module.c
index 159a2b81e90c..6e81bb596e5b 100644
--- a/arch/parisc/kernel/module.c
+++ b/arch/parisc/kernel/module.c
@@ -941,11 +941,10 @@ int module_finalize(const Elf_Ehdr *hdr,
941 nsyms = newptr - (Elf_Sym *)symhdr->sh_addr; 941 nsyms = newptr - (Elf_Sym *)symhdr->sh_addr;
942 DEBUGP("NEW num_symtab %lu\n", nsyms); 942 DEBUGP("NEW num_symtab %lu\n", nsyms);
943 symhdr->sh_size = nsyms * sizeof(Elf_Sym); 943 symhdr->sh_size = nsyms * sizeof(Elf_Sym);
944 return module_bug_finalize(hdr, sechdrs, me); 944 return 0;
945} 945}
946 946
947void module_arch_cleanup(struct module *mod) 947void module_arch_cleanup(struct module *mod)
948{ 948{
949 deregister_unwind_table(mod); 949 deregister_unwind_table(mod);
950 module_bug_cleanup(mod);
951} 950}
diff --git a/arch/powerpc/kernel/module.c b/arch/powerpc/kernel/module.c
index 477c663e0140..4ef93ae2235f 100644
--- a/arch/powerpc/kernel/module.c
+++ b/arch/powerpc/kernel/module.c
@@ -65,10 +65,6 @@ int module_finalize(const Elf_Ehdr *hdr,
65 const Elf_Shdr *sect; 65 const Elf_Shdr *sect;
66 int err; 66 int err;
67 67
68 err = module_bug_finalize(hdr, sechdrs, me);
69 if (err)
70 return err;
71
72 /* Apply feature fixups */ 68 /* Apply feature fixups */
73 sect = find_section(hdr, sechdrs, "__ftr_fixup"); 69 sect = find_section(hdr, sechdrs, "__ftr_fixup");
74 if (sect != NULL) 70 if (sect != NULL)
@@ -101,5 +97,4 @@ int module_finalize(const Elf_Ehdr *hdr,
101 97
102void module_arch_cleanup(struct module *mod) 98void module_arch_cleanup(struct module *mod)
103{ 99{
104 module_bug_cleanup(mod);
105} 100}
diff --git a/arch/s390/kernel/module.c b/arch/s390/kernel/module.c
index 22cfd634c355..f7167ee4604c 100644
--- a/arch/s390/kernel/module.c
+++ b/arch/s390/kernel/module.c
@@ -407,10 +407,9 @@ int module_finalize(const Elf_Ehdr *hdr,
407{ 407{
408 vfree(me->arch.syminfo); 408 vfree(me->arch.syminfo);
409 me->arch.syminfo = NULL; 409 me->arch.syminfo = NULL;
410 return module_bug_finalize(hdr, sechdrs, me); 410 return 0;
411} 411}
412 412
413void module_arch_cleanup(struct module *mod) 413void module_arch_cleanup(struct module *mod)
414{ 414{
415 module_bug_cleanup(mod);
416} 415}
diff --git a/arch/sh/kernel/module.c b/arch/sh/kernel/module.c
index 43adddfe4c04..ae0be697a89e 100644
--- a/arch/sh/kernel/module.c
+++ b/arch/sh/kernel/module.c
@@ -149,13 +149,11 @@ int module_finalize(const Elf_Ehdr *hdr,
149 int ret = 0; 149 int ret = 0;
150 150
151 ret |= module_dwarf_finalize(hdr, sechdrs, me); 151 ret |= module_dwarf_finalize(hdr, sechdrs, me);
152 ret |= module_bug_finalize(hdr, sechdrs, me);
153 152
154 return ret; 153 return ret;
155} 154}
156 155
157void module_arch_cleanup(struct module *mod) 156void module_arch_cleanup(struct module *mod)
158{ 157{
159 module_bug_cleanup(mod);
160 module_dwarf_cleanup(mod); 158 module_dwarf_cleanup(mod);
161} 159}
diff --git a/arch/x86/kernel/module.c b/arch/x86/kernel/module.c
index e0bc186d7501..1c355c550960 100644
--- a/arch/x86/kernel/module.c
+++ b/arch/x86/kernel/module.c
@@ -239,11 +239,10 @@ int module_finalize(const Elf_Ehdr *hdr,
239 apply_paravirt(pseg, pseg + para->sh_size); 239 apply_paravirt(pseg, pseg + para->sh_size);
240 } 240 }
241 241
242 return module_bug_finalize(hdr, sechdrs, me); 242 return 0;
243} 243}
244 244
245void module_arch_cleanup(struct module *mod) 245void module_arch_cleanup(struct module *mod)
246{ 246{
247 alternatives_smp_module_del(mod); 247 alternatives_smp_module_del(mod);
248 module_bug_cleanup(mod);
249} 248}