• Jan Kara's avatar
    bdi: Fix oops in wb_workfn() · 683b4520
    Jan Kara authored
    commit b8b784958eccbf8f51ebeee65282ca3fd59ea391 upstream.
    
    Syzbot has reported that it can hit a NULL pointer dereference in
    wb_workfn() due to wb->bdi->dev being NULL. This indicates that
    wb_workfn() was called for an already unregistered bdi which should not
    happen as wb_shutdown() called from bdi_unregister() should make sure
    all pending writeback works are completed before bdi is unregistered.
    Except that wb_workfn() itself can requeue the work with:
    
    	mod_delayed_work(bdi_wq, &wb->dwork, 0);
    
    and if this happens while wb_shutdown() is waiting in:
    
    	flush_delayed_work(&wb->dwork);
    
    the dwork can get executed after wb_shutdown() has finished and
    bdi_unregister() has cleared wb->bdi->dev.
    
    Make wb_workfn() use wakeup_wb() for requeueing the work which takes all
    the necessary precautions against racing with bdi unregistration.
    
    CC: Tetsuo Handa <penguin-kernel@I-love.SAKURA.ne.jp>
    CC: Tejun Heo <tj@kernel.org>
    Fixes: 839a8e86Reported-by: 's avatarsyzbot <syzbot+9873874c735f2892e7e9@syzkaller.appspotmail.com>
    Reviewed-by: 's avatarDave Chinner <dchinner@redhat.com>
    Signed-off-by: 's avatarJan Kara <jack@suse.cz>
    Signed-off-by: 's avatarJens Axboe <axboe@kernel.dk>
    Signed-off-by: 's avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
    683b4520