Fix a bug when we free module's memory while a timer is pending by canceling all deferred timers from the unloaded module. static_key_rate_limit() still can't be called more than once. Reproducer: (host crasher) modprobe kvm_intel (sleep 1; echo quit) \ | qemu-kvm -kernel /dev/null -monitor stdio & sleep 0.5 until modprobe -rv kvm_intel 2>/dev/null; do :; done Signed-off-by: Radim Krčmář <rkrcmar@xxxxxxxxxx> --- I decided not to post a patch that uses __deferred_key in kernel/module init, so these three functions might seem like an overkill. kernel/jump_label.c | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/kernel/jump_label.c b/kernel/jump_label.c index 9019f15..02d610a 100644 --- a/kernel/jump_label.c +++ b/kernel/jump_label.c @@ -125,6 +125,27 @@ void jump_label_rate_limit(struct static_key_deferred *key, } EXPORT_SYMBOL_GPL(jump_label_rate_limit); +/* could (should?) be abstracted more */ +static void with_deferred_keys(struct static_key_deferred *entry, + struct static_key_deferred *stop, + void (*op)(struct static_key_deferred *)) +{ + struct static_key_deferred *iter; + + for (iter = entry; iter < stop; iter++) + op(iter); +} + +#define with_module_deferred_keys(mod, op) \ + with_deferred_keys(mod->deferred_keys, \ + mod->deferred_keys + mod->num_deferred_keys, \ + op) + +static void deferred_key_cancel_work(struct static_key_deferred *dkey) +{ + cancel_delayed_work_sync(&dkey->work); +} + static int addr_conflict(struct jump_entry *entry, void *start, void *end) { if (entry->code <= (unsigned long)end && @@ -385,6 +406,7 @@ jump_label_module_notify(struct notifier_block *self, unsigned long val, jump_label_unlock(); break; case MODULE_STATE_GOING: + with_module_deferred_keys(mod, deferred_key_cancel_work); jump_label_lock(); jump_label_del_module(mod); jump_label_unlock(); -- 1.8.4.2 -- To unsubscribe from this list: send the line "unsubscribe linux-arch" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html