aboutsummaryrefslogtreecommitdiffstats
path: root/arch/i386/kernel
diff options
context:
space:
mode:
authorJan Beulich <jbeulich@novell.com>2006-03-23 05:59:45 -0500
committerLinus Torvalds <torvalds@g5.osdl.org>2006-03-23 10:38:05 -0500
commit101f12af16fb12f8da8100899a13ee1b1b576a0a (patch)
tree0bea73d2702ba438e8e82bc8000b498aa50aee6e /arch/i386/kernel
parent44fd22992cb76dc51c52cf4b8aff1bc7899bb23c (diff)
[PATCH] i386: actively synchronize vmalloc area when registering certain callbacks
Registering a callback handler through register_die_notifier() is obviously primarily intended for use by modules. However, the way these currently get called it is basically impossible for them to actually be used by modules, as there is, on non-PAE configurationes, a good chance (the larger the module, the better) for the system to crash as a result. This is because the callback gets invoked (a) in the page fault path before the top level page table propagation gets carried out (hence a fault to propagate the top level page table entry/entries mapping to module's code/data would nest infinitly) and (b) in the NMI path, where nested faults must absolutely not happen, since otherwise the IRET from the nested fault re-enables NMIs, potentially resulting in nested NMI occurences. Besides the modular aspect, similar problems would even arise for in- kernel consumers of the API if they touched ioremap()ed or vmalloc()ed memory inside their handlers. Signed-off-by: Jan Beulich <jbeulich@novell.com> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Diffstat (limited to 'arch/i386/kernel')
-rw-r--r--arch/i386/kernel/traps.c3
1 files changed, 3 insertions, 0 deletions
diff --git a/arch/i386/kernel/traps.c b/arch/i386/kernel/traps.c
index f20797b8da1d..d510de7e4f2a 100644
--- a/arch/i386/kernel/traps.c
+++ b/arch/i386/kernel/traps.c
@@ -99,6 +99,8 @@ int register_die_notifier(struct notifier_block *nb)
99{ 99{
100 int err = 0; 100 int err = 0;
101 unsigned long flags; 101 unsigned long flags;
102
103 vmalloc_sync_all();
102 spin_lock_irqsave(&die_notifier_lock, flags); 104 spin_lock_irqsave(&die_notifier_lock, flags);
103 err = notifier_chain_register(&i386die_chain, nb); 105 err = notifier_chain_register(&i386die_chain, nb);
104 spin_unlock_irqrestore(&die_notifier_lock, flags); 106 spin_unlock_irqrestore(&die_notifier_lock, flags);
@@ -713,6 +715,7 @@ fastcall void do_nmi(struct pt_regs * regs, long error_code)
713 715
714void set_nmi_callback(nmi_callback_t callback) 716void set_nmi_callback(nmi_callback_t callback)
715{ 717{
718 vmalloc_sync_all();
716 rcu_assign_pointer(nmi_callback, callback); 719 rcu_assign_pointer(nmi_callback, callback);
717} 720}
718EXPORT_SYMBOL_GPL(set_nmi_callback); 721EXPORT_SYMBOL_GPL(set_nmi_callback);