• Jan Kara's avatar
    bdi: Fix oops in wb_workfn() · b8b78495
    Jan Kara authored
    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: default avatarsyzbot <syzbot+9873874c735f2892e7e9@syzkaller.appspotmail.com>
    Reviewed-by: default avatarDave Chinner <dchinner@redhat.com>
    Signed-off-by: default avatarJan Kara <jack@suse.cz>
    Signed-off-by: default avatarJens Axboe <axboe@kernel.dk>
    b8b78495
fs-writeback.c 70.7 KB