Skip to content

Commit 3c9b2c3

Browse files
Peter ZijlstraIngo Molnar
authored andcommitted
sched, modules: Fix nested sleep in add_unformed_module()
This is a genuine bug in add_unformed_module(), we cannot use blocking primitives inside a wait loop. So rewrite the wait_event_interruptible() usage to use the fresh wait_woken() stuff. Reported-by: Fengguang Wu <[email protected]> Signed-off-by: Peter Zijlstra (Intel) <[email protected]> Cc: [email protected] Cc: [email protected] Cc: [email protected] Cc: Rusty Russell <[email protected]> Cc: [email protected] Cc: Linus Torvalds <[email protected]> Cc: Andrew Morton <[email protected]> Cc: Greg Kroah-Hartman <[email protected]> Link: http://lkml.kernel.org/r/[email protected] [ So this is probably complex to backport and the race wasn't reported AFAIK, so not marked for -stable. ] Signed-off-by: Ingo Molnar <[email protected]> Signed-off-by: Ingo Molnar <[email protected]>
1 parent 7d4d269 commit 3c9b2c3

File tree

1 file changed

+28
-2
lines changed

1 file changed

+28
-2
lines changed

kernel/module.c

Lines changed: 28 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3096,6 +3096,32 @@ static int may_init_module(void)
30963096
return 0;
30973097
}
30983098

3099+
/*
3100+
* Can't use wait_event_interruptible() because our condition
3101+
* 'finished_loading()' contains a blocking primitive itself (mutex_lock).
3102+
*/
3103+
static int wait_finished_loading(struct module *mod)
3104+
{
3105+
DEFINE_WAIT_FUNC(wait, woken_wake_function);
3106+
int ret = 0;
3107+
3108+
add_wait_queue(&module_wq, &wait);
3109+
for (;;) {
3110+
if (finished_loading(mod->name))
3111+
break;
3112+
3113+
if (signal_pending(current)) {
3114+
ret = -ERESTARTSYS;
3115+
break;
3116+
}
3117+
3118+
wait_woken(&wait, TASK_INTERRUPTIBLE, MAX_SCHEDULE_TIMEOUT);
3119+
}
3120+
remove_wait_queue(&module_wq, &wait);
3121+
3122+
return ret;
3123+
}
3124+
30993125
/*
31003126
* We try to place it in the list now to make sure it's unique before
31013127
* we dedicate too many resources. In particular, temporary percpu
@@ -3116,8 +3142,8 @@ static int add_unformed_module(struct module *mod)
31163142
|| old->state == MODULE_STATE_UNFORMED) {
31173143
/* Wait in case it fails to load. */
31183144
mutex_unlock(&module_mutex);
3119-
err = wait_event_interruptible(module_wq,
3120-
finished_loading(mod->name));
3145+
3146+
err = wait_finished_loading(mod);
31213147
if (err)
31223148
goto out_unlocked;
31233149
goto again;

0 commit comments

Comments
 (0)