Skip to content
  • Tetsuo Handa's avatar
    kmod: avoid deadlock from recursive kmod call · 0f20784d
    Tetsuo Handa authored
    
    
    The system deadlocks (at least since 2.6.10) when
    call_usermodehelper(UMH_WAIT_EXEC) request triggers
    call_usermodehelper(UMH_WAIT_PROC) request.
    
    This is because "khelper thread is waiting for the worker thread at
    wait_for_completion() in do_fork() since the worker thread was created
    with CLONE_VFORK flag" and "the worker thread cannot call complete()
    because do_execve() is blocked at UMH_WAIT_PROC request" and "the khelper
    thread cannot start processing UMH_WAIT_PROC request because the khelper
    thread is waiting for the worker thread at wait_for_completion() in
    do_fork()".
    
    The easiest example to observe this deadlock is to use a corrupted
    /sbin/hotplug binary (like shown below).
    
      # : > /tmp/dummy
      # chmod 755 /tmp/dummy
      # echo /tmp/dummy > /proc/sys/kernel/hotplug
      # modprobe whatever
    
    call_usermodehelper("/tmp/dummy", UMH_WAIT_EXEC) is called from
    kobject_uevent_env() in lib/kobject_uevent.c upon loading/unloading a
    module.  do_execve("/tmp/dummy") triggers a call to
    request_module("binfmt-0000") from search_binary_handler() which in turn
    calls call_usermodehelper(UMH_WAIT_PROC).
    
    In order to avoid deadlock, as a for-now and easy-to-backport solution, do
    not try to call wait_for_completion() in call_usermodehelper_exec() if the
    worker thread was created by khelper thread with CLONE_VFORK flag.  Future
    and fundamental solution might be replacing singleton khelper thread with
    some workqueue so that recursive calls up to max_active dependency loop
    can be handled without deadlock.
    
    [akpm@linux-foundation.org: add comment to kmod_thread_locker]
    Signed-off-by: default avatarTetsuo Handa <penguin-kernel@I-love.SAKURA.ne.jp>
    Cc: Arjan van de Ven <arjan@linux.intel.com>
    Acked-by: default avatarRusty Russell <rusty@rustcorp.com.au>
    Cc: Tejun Heo <tj@kernel.org>
    Cc: Oleg Nesterov <oleg@redhat.com>
    Signed-off-by: default avatarAndrew Morton <akpm@linux-foundation.org>
    Signed-off-by: default avatarLinus Torvalds <torvalds@linux-foundation.org>
    0f20784d