• Li Bin's avatar
    workqueue: Fix NULL pointer dereference · 46f15501
    Li Bin authored
    commit cef572ad upstream.
    
    When queue_work() is used in irq (not in task context), there is
    a potential case that trigger NULL pointer dereference.
    ----------------------------------------------------------------
    worker_thread()
    |-spin_lock_irq()
    |-process_one_work()
    	|-worker->current_pwq = pwq
    	|-spin_unlock_irq()
    	|-worker->current_func(work)
    	|-spin_lock_irq()
     	|-worker->current_pwq = NULL
    |-spin_unlock_irq()
    
    				//interrupt here
    				|-irq_handler
    					|-__queue_work()
    						//assuming that the wq is draining
    						|-is_chained_work(wq)
    							|-current_wq_worker()
    							//Here, 'current' is the interrupted worker!
    								|-current->current_pwq is NULL here!
    |-schedule()
    ----------------------------------------------------------------
    
    Avoid it by checking for task context in current_wq_worker(), and
    if not in task context, we shouldn't use the 'current' to check the
    condition.
    Reported-by: 's avatarXiaofei Tan <tanxiaofei@huawei.com>
    Signed-off-by: 's avatarLi Bin <huawei.libin@huawei.com>
    Reviewed-by: 's avatarLai Jiangshan <jiangshanlai@gmail.com>
    Signed-off-by: 's avatarTejun Heo <tj@kernel.org>
    Fixes: 8d03ecfe ("workqueue: reimplement is_chained_work() using current_wq_worker()")
    Signed-off-by: 's avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
    46f15501
workqueue_internal.h 2.24 KB