summaryrefslogtreecommitdiff
path: root/kernels/linux-libre-grsec/module-symbol-waiting-3.6.patch
diff options
context:
space:
mode:
authorNicolás Reynolds <apoyosis@correo.inta.gob.ar>2012-11-21 14:35:33 -0300
committerNicolás Reynolds <apoyosis@correo.inta.gob.ar>2012-11-21 14:35:33 -0300
commit6db0365f800f4d3411cad96b6a5594e723ede007 (patch)
tree9d3184fdd7ebf5336ec0bcdbdd39a68b83d08a9e /kernels/linux-libre-grsec/module-symbol-waiting-3.6.patch
parentcdc73ac802a1af7a5e797e2789db591b244787be (diff)
parent7e1e84043f1e7fcc36ab23acc9f9df97f814d819 (diff)
downloadabslibre-6db0365f800f4d3411cad96b6a5594e723ede007.tar.gz
abslibre-6db0365f800f4d3411cad96b6a5594e723ede007.tar.bz2
abslibre-6db0365f800f4d3411cad96b6a5594e723ede007.zip
Merge branch 'master' of ssh://gparabola/srv/git/abslibre
Diffstat (limited to 'kernels/linux-libre-grsec/module-symbol-waiting-3.6.patch')
-rw-r--r--kernels/linux-libre-grsec/module-symbol-waiting-3.6.patch66
1 files changed, 66 insertions, 0 deletions
diff --git a/kernels/linux-libre-grsec/module-symbol-waiting-3.6.patch b/kernels/linux-libre-grsec/module-symbol-waiting-3.6.patch
new file mode 100644
index 000000000..b87a38ff5
--- /dev/null
+++ b/kernels/linux-libre-grsec/module-symbol-waiting-3.6.patch
@@ -0,0 +1,66 @@
+From: Rusty Russell <rusty@rustcorp.com.au>
+Date: Fri, 28 Sep 2012 05:01:03 +0000 (+0930)
+Subject: module: fix symbol waiting when module fails before init
+X-Git-Tag: v3.7-rc1~2^2~33
+X-Git-Url: http://git.kernel.org/?p=linux%2Fkernel%2Fgit%2Ftorvalds%2Flinux-2.6.git;a=commitdiff_plain;h=6f13909f4fe9652f1
+
+module: fix symbol waiting when module fails before init
+
+We use resolve_symbol_wait(), which blocks if the module containing
+the symbol is still loading. However:
+
+1) The module_wq we use is only woken after calling the modules' init
+ function, but there are other failure paths after the module is
+ placed in the linked list where we need to do the same thing.
+
+2) wake_up() only wakes one waiter, and our waitqueue is shared by all
+ modules, so we need to wake them all.
+
+3) wake_up_all() doesn't imply a memory barrier: I feel happier calling
+ it after we've grabbed and dropped the module_mutex, not just after
+ the state assignment.
+
+Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
+---
+
+diff --git a/kernel/module.c b/kernel/module.c
+index 7f2ee45f..63cf6e7 100644
+--- a/kernel/module.c
++++ b/kernel/module.c
+@@ -2959,7 +2959,7 @@ static struct module *load_module(void __user *umod,
+ /* Unlink carefully: kallsyms could be walking list. */
+ list_del_rcu(&mod->list);
+ module_bug_cleanup(mod);
+-
++ wake_up_all(&module_wq);
+ ddebug:
+ dynamic_debug_remove(info.debug);
+ unlock:
+@@ -3034,7 +3034,7 @@ SYSCALL_DEFINE3(init_module, void __user *, umod,
+ blocking_notifier_call_chain(&module_notify_list,
+ MODULE_STATE_GOING, mod);
+ free_module(mod);
+- wake_up(&module_wq);
++ wake_up_all(&module_wq);
+ return ret;
+ }
+ if (ret > 0) {
+@@ -3046,9 +3046,8 @@ SYSCALL_DEFINE3(init_module, void __user *, umod,
+ dump_stack();
+ }
+
+- /* Now it's a first class citizen! Wake up anyone waiting for it. */
++ /* Now it's a first class citizen! */
+ mod->state = MODULE_STATE_LIVE;
+- wake_up(&module_wq);
+ blocking_notifier_call_chain(&module_notify_list,
+ MODULE_STATE_LIVE, mod);
+
+@@ -3071,6 +3070,7 @@ SYSCALL_DEFINE3(init_module, void __user *, umod,
+ mod->init_ro_size = 0;
+ mod->init_text_size = 0;
+ mutex_unlock(&module_mutex);
++ wake_up_all(&module_wq);
+
+ return 0;
+ }