From: Ming Lei ming.lei@redhat.com
mainline inclusion from mainline-5.10-rc5 commit 9f16a66733c90b5f33f624b0b0e36a345b0aaf93 category: bugfix bugzilla: 45589 CVE: NA
-------------------------------------------------
For avoiding use-after-free on flush request, we call its .end_io() from both timeout code path and __blk_mq_end_request().
When flush request's ref doesn't drop to zero, it is still used, we can't mark it as IDLE, so fix it by marking IDLE when its refcount drops to zero really.
Fixes: 65ff5cd04551 ("blk-mq: mark flush request as IDLE in flush_end_io()") Signed-off-by: Ming Lei ming.lei@redhat.com Cc: Yi Zhang yi.zhang@redhat.com Signed-off-by: Jens Axboe axboe@kernel.dk
Conflicts: block/blk-flush.c
Signed-off-by: Baokun Li libaokun1@huawei.com Reviewed-by: Yufen Yu yuyufen@huawei.com Signed-off-by: Yang Yingliang yangyingliang@huawei.com --- block/blk-flush.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-)
diff --git a/block/blk-flush.c b/block/blk-flush.c index c1ba915658a2c..c357e5c16d89c 100644 --- a/block/blk-flush.c +++ b/block/blk-flush.c @@ -233,13 +233,18 @@ static void flush_end_io(struct request *flush_rq, blk_status_t error) /* release the tag's ownership to the req cloned from */ spin_lock_irqsave(&fq->mq_flush_lock, flags);
- WRITE_ONCE(flush_rq->state, MQ_RQ_IDLE); if (!refcount_dec_and_test(&flush_rq->ref)) { fq->rq_status = error; spin_unlock_irqrestore(&fq->mq_flush_lock, flags); return; }
+ /* + * Flush request has to be marked as IDLE when it is really ended + * because its .end_io() is called from timeout code path too for + * avoiding use-after-free. + */ + WRITE_ONCE(flush_rq->state, MQ_RQ_IDLE); if (fq->rq_status != BLK_STS_OK) error = fq->rq_status;