Backport 5336377d6225959624146629ce3fc88ee8ecda3d for RHBZ 648571
This commit is contained in:
parent
d078fed40e
commit
cf5a635e41
11
kernel.spec
11
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@redhat.com>
|
||||
- Backport 5336377d to fix RHBZ #648571
|
||||
|
||||
* Wed Aug 31 2011 Josh Boyer <jwboyer@redhat.com> 2.6.35.14-96
|
||||
- Add patch to fix RHBZ #665109
|
||||
|
||||
|
|
|
@ -0,0 +1,271 @@
|
|||
From 9aad2d11106f9a42593ee8eb3f10bc469873a18e Mon Sep 17 00:00:00 2001
|
||||
From: Linus Torvalds <torvalds@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@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>
|
||||
---
|
||||
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
|
||||
|
Loading…
Reference in New Issue