• Ming Lei's avatar
    blk-mq: fix kernel panic during iterating over flush request · c2da19ed
    Ming Lei authored
    For fixing use-after-free during iterating over requests, we grabbed
    request's refcount before calling ->fn in commit 2e315dc0 ("blk-mq:
    grab rq->refcount before calling ->fn in blk_mq_tagset_busy_iter").
    Turns out this way may cause kernel panic when iterating over one flush
    request:
    
    1) old flush request's tag is just released, and this tag is reused by
    one new request, but ->rqs[] isn't updated yet
    
    2) the flush request can be re-used for submitting one new flush command,
    so blk_rq_init() is called at the same time
    
    3) meantime blk_mq_queue_tag_busy_iter() is called, and old flush request
    is retrieved from ->rqs[tag]; when blk_mq_put_rq_ref() is called,
    flush_rq->end_io may not be updated yet, so NULL pointer dereference
    is triggered in blk_mq_put_rq_ref().
    
    Fix the issue by calling refcount_set(&flush_rq->ref, 1) after
    flush_rq->end_io is set. So far the only other caller of blk_rq_init() is
    scsi_ioctl_reset() in which the request doesn'...
    c2da19ed
blk-core.c 47.3 KB