Skip to content

Commit c8cdc02

Browse files
damien-lemoalgregkh
authored andcommitted
block: fix NULL pointer dereference in blk_zone_reset_all_bio_endio()
commit c2b8d20 upstream. For zoned block devices that do not need zone write plugs (e.g. most device mapper devices that support zones), the disk hash table of zone write plugs is NULL. For such devices, blk_zone_reset_all_bio_endio() should not attempt to scan this has table as that causes a NULL pointer dereference. Fix this by checking that the disk does have zone write plugs using the atomic counter. This is equivalent to checking for a non-NULL hash table but has the advantage to also speed up the execution of blk_zone_reset_all_bio_endio() for devices that do use zone write plugs but do not have any plug in the hash table (e.g. a disk with only full zones). Fixes: efae226 ("block: handle zone management operations completions") Reported-by: Shin'ichiro Kawasaki <shinichiro.kawasaki@wdc.com> Signed-off-by: Damien Le Moal <dlemoal@kernel.org> Reviewed-by: Christoph Hellwig <hch@lst.de> Signed-off-by: Jens Axboe <axboe@kernel.dk> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
1 parent 5129768 commit c8cdc02

File tree

1 file changed

+12
-9
lines changed

1 file changed

+12
-9
lines changed

block/blk-zoned.c

Lines changed: 12 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -746,17 +746,20 @@ static void blk_zone_reset_all_bio_endio(struct bio *bio)
746746
unsigned long flags;
747747
unsigned int i;
748748

749-
/* Update the condition of all zone write plugs. */
750-
rcu_read_lock();
751-
for (i = 0; i < disk_zone_wplugs_hash_size(disk); i++) {
752-
hlist_for_each_entry_rcu(zwplug, &disk->zone_wplugs_hash[i],
753-
node) {
754-
spin_lock_irqsave(&zwplug->lock, flags);
755-
disk_zone_wplug_set_wp_offset(disk, zwplug, 0);
756-
spin_unlock_irqrestore(&zwplug->lock, flags);
749+
if (atomic_read(&disk->nr_zone_wplugs)) {
750+
/* Update the condition of all zone write plugs. */
751+
rcu_read_lock();
752+
for (i = 0; i < disk_zone_wplugs_hash_size(disk); i++) {
753+
hlist_for_each_entry_rcu(zwplug,
754+
&disk->zone_wplugs_hash[i],
755+
node) {
756+
spin_lock_irqsave(&zwplug->lock, flags);
757+
disk_zone_wplug_set_wp_offset(disk, zwplug, 0);
758+
spin_unlock_irqrestore(&zwplug->lock, flags);
759+
}
757760
}
761+
rcu_read_unlock();
758762
}
759-
rcu_read_unlock();
760763
}
761764

762765
static void blk_zone_finish_bio_endio(struct bio *bio)

0 commit comments

Comments
 (0)