diff options
author | Yu Kuai <yukuai3@huawei.com> | 2023-05-31 09:34:35 +0200 |
---|---|---|
committer | Jens Axboe <axboe@kernel.dk> | 2023-06-01 17:13:31 +0200 |
commit | 5a0ac57c48aa9380126bd9bf3ec82140aab84548 (patch) | |
tree | 7d440f4a22f244eea9dfbcd27edc62457f923c9a /block/genhd.c | |
parent | block: mark bio_add_folio as __must_check (diff) | |
download | linux-5a0ac57c48aa9380126bd9bf3ec82140aab84548.tar.xz linux-5a0ac57c48aa9380126bd9bf3ec82140aab84548.zip |
blk-ioc: protect ioc_destroy_icq() by 'queue_lock'
Currently, icq is tracked by both request_queue(icq->q_node) and
task(icq->ioc_node), and ioc_clear_queue() from elevator exit is not
safe because it can access the list without protection:
ioc_clear_queue ioc_release_fn
lock queue_lock
list_splice
/* move queue list to a local list */
unlock queue_lock
/*
* lock is released, the local list
* can be accessed through task exit.
*/
lock ioc->lock
while (!hlist_empty)
icq = hlist_entry
lock queue_lock
ioc_destroy_icq
delete icq->ioc_node
while (!list_empty)
icq = list_entry() list_del icq->q_node
/*
* This is not protected by any lock,
* list_entry concurrent with list_del
* is not safe.
*/
unlock queue_lock
unlock ioc->lock
Fix this problem by protecting list 'icq->q_node' by queue_lock from
ioc_clear_queue().
Reported-and-tested-by: Pradeep Pragallapati <quic_pragalla@quicinc.com>
Link: https://lore.kernel.org/lkml/20230517084434.18932-1-quic_pragalla@quicinc.com/
Signed-off-by: Yu Kuai <yukuai3@huawei.com>
Reviewed-by: Christoph Hellwig <hch@lst.de>
Link: https://lore.kernel.org/r/20230531073435.2923422-1-yukuai1@huaweicloud.com
Signed-off-by: Jens Axboe <axboe@kernel.dk>
Diffstat (limited to 'block/genhd.c')
0 files changed, 0 insertions, 0 deletions