Skip to content

Commit c749637

Browse files
committed
module: fix race in kallsyms resolution during module load success.
The kallsyms routines (module_symbol_name, lookup_module_* etc) disable preemption to walk the modules rather than taking the module_mutex: this is because they are used for symbol resolution during oopses. This works because there are synchronize_sched() and synchronize_rcu() in the unload and failure paths. However, there's one case which doesn't have that: the normal case where module loading succeeds, and we free the init section. We don't want a synchronize_rcu() there, because it would slow down module loading: this bug was introduced in 2009 to speed module loading in the first place. Thus, we want to do the free in an RCU callback. We do this in the simplest possible way by allocating a new rcu_head: if we put it in the module structure we'd have to worry about that getting freed. Reported-by: Rui Xiang <[email protected]> Signed-off-by: Rusty Russell <[email protected]>
1 parent be1f221 commit c749637

File tree

1 file changed

+42
-13
lines changed

1 file changed

+42
-13
lines changed

kernel/module.c

Lines changed: 42 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -2989,10 +2989,31 @@ static void do_mod_ctors(struct module *mod)
29892989
#endif
29902990
}
29912991

2992+
/* For freeing module_init on success, in case kallsyms traversing */
2993+
struct mod_initfree {
2994+
struct rcu_head rcu;
2995+
void *module_init;
2996+
};
2997+
2998+
static void do_free_init(struct rcu_head *head)
2999+
{
3000+
struct mod_initfree *m = container_of(head, struct mod_initfree, rcu);
3001+
module_memfree(m->module_init);
3002+
kfree(m);
3003+
}
3004+
29923005
/* This is where the real work happens */
29933006
static int do_init_module(struct module *mod)
29943007
{
29953008
int ret = 0;
3009+
struct mod_initfree *freeinit;
3010+
3011+
freeinit = kmalloc(sizeof(*freeinit), GFP_KERNEL);
3012+
if (!freeinit) {
3013+
ret = -ENOMEM;
3014+
goto fail;
3015+
}
3016+
freeinit->module_init = mod->module_init;
29963017

29973018
/*
29983019
* We want to find out whether @mod uses async during init. Clear
@@ -3005,18 +3026,7 @@ static int do_init_module(struct module *mod)
30053026
if (mod->init != NULL)
30063027
ret = do_one_initcall(mod->init);
30073028
if (ret < 0) {
3008-
/*
3009-
* Init routine failed: abort. Try to protect us from
3010-
* buggy refcounters.
3011-
*/
3012-
mod->state = MODULE_STATE_GOING;
3013-
synchronize_sched();
3014-
module_put(mod);
3015-
blocking_notifier_call_chain(&module_notify_list,
3016-
MODULE_STATE_GOING, mod);
3017-
free_module(mod);
3018-
wake_up_all(&module_wq);
3019-
return ret;
3029+
goto fail_free_freeinit;
30203030
}
30213031
if (ret > 0) {
30223032
pr_warn("%s: '%s'->init suspiciously returned %d, it should "
@@ -3062,15 +3072,34 @@ static int do_init_module(struct module *mod)
30623072
#endif
30633073
unset_module_init_ro_nx(mod);
30643074
module_arch_freeing_init(mod);
3065-
module_memfree(mod->module_init);
30663075
mod->module_init = NULL;
30673076
mod->init_size = 0;
30683077
mod->init_ro_size = 0;
30693078
mod->init_text_size = 0;
3079+
/*
3080+
* We want to free module_init, but be aware that kallsyms may be
3081+
* walking this with preempt disabled. In all the failure paths,
3082+
* we call synchronize_rcu/synchronize_sched, but we don't want
3083+
* to slow down the success path, so use actual RCU here.
3084+
*/
3085+
call_rcu(&freeinit->rcu, do_free_init);
30703086
mutex_unlock(&module_mutex);
30713087
wake_up_all(&module_wq);
30723088

30733089
return 0;
3090+
3091+
fail_free_freeinit:
3092+
kfree(freeinit);
3093+
fail:
3094+
/* Try to protect us from buggy refcounters. */
3095+
mod->state = MODULE_STATE_GOING;
3096+
synchronize_sched();
3097+
module_put(mod);
3098+
blocking_notifier_call_chain(&module_notify_list,
3099+
MODULE_STATE_GOING, mod);
3100+
free_module(mod);
3101+
wake_up_all(&module_wq);
3102+
return ret;
30743103
}
30753104

30763105
static int may_init_module(void)

0 commit comments

Comments
 (0)