• Z
    block: fix null-deref in percpu_ref_put · 51ddf58f
    Zhang Wensheng 提交于
    hulk inclusion
    category: bugfix
    bugzilla: https://gitee.com/openeuler/kernel/issues/I5N162
    CVE: NA
    
    --------------------------------
    
    In the use of q_usage_counter of request_queue, blk_cleanup_queue using
    "wait_event(q->mq_freeze_wq, percpu_ref_is_zero(&q->q_usage_counter))"
    to wait q_usage_counter becoming zero. however, if the q_usage_counter
    becoming zero quickly, and percpu_ref_exit will execute and ref->data
    will be freed, maybe another process will cause a null-defef problem
    like below:
    
    	CPU0                             CPU1
    blk_cleanup_queue
     blk_freeze_queue
      blk_mq_freeze_queue_wait
    				scsi_end_request
    				 percpu_ref_get
    				 ...
    				 percpu_ref_put
    				  atomic_long_sub_and_test
      percpu_ref_exit
       ref->data -> NULL
       				   ref->data->release(ref) -> null-deref
    
    Fix it by setting flag(QUEUE_FLAG_USAGE_COUNT_SYNC) to add synchronization
    mechanism, when ref->data->release is called, the flag will be setted,
    and the "wait_event" in blk_mq_freeze_queue_wait must wait flag becoming
    true as well, which will limit percpu_ref_exit to execute ahead of time.
    Signed-off-by: NZhang Wensheng <zhangwensheng5@huawei.com>
    Reviewed-by: NYu Kuai <yukuai3@huawei.com>
    Signed-off-by: NZheng Zengkai <zhengzengkai@huawei.com>
    51ddf58f
blk-mq.h 19.6 KB