A virtio_blk block device can still be referenced after hot unplug by userspace processes that hold the file descriptor. In this case virtblk_getgeo() can be invoked after virtblk_remove() was called. For example, a program that has /dev/vdb open can call ioctl(HDIO_GETGEO) after hot unplug. Fix this by clearing vblk->disk->private_data and checking that the virtio_blk driver instance is still around in virtblk_getgeo(). Note that the virtblk_getgeo() function itself is guaranteed to remain in memory after hot unplug because the virtio_blk module refcount is still held while a block device reference exists. Originally-by: Lance Digby <ldigby@xxxxxxxxxx> Signed-off-by: Stefan Hajnoczi <stefanha@xxxxxxxxxx> --- drivers/block/virtio_blk.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/drivers/block/virtio_blk.c b/drivers/block/virtio_blk.c index 93468b7c6701..b50cdf37a6f7 100644 --- a/drivers/block/virtio_blk.c +++ b/drivers/block/virtio_blk.c @@ -300,6 +300,10 @@ static int virtblk_getgeo(struct block_device *bd, struct hd_geometry *geo) { struct virtio_blk *vblk = bd->bd_disk->private_data; + /* Driver instance has been removed */ + if (!vblk) + return -ENOTTY; + /* see if the host passed in geometry config */ if (virtio_has_feature(vblk->vdev, VIRTIO_BLK_F_GEOMETRY)) { virtio_cread(vblk->vdev, struct virtio_blk_config, @@ -835,6 +839,7 @@ static void virtblk_remove(struct virtio_device *vdev) vdev->config->reset(vdev); refc = kref_read(&disk_to_dev(vblk->disk)->kobj.kref); + vblk->disk->private_data = NULL; put_disk(vblk->disk); vdev->config->del_vqs(vdev); kfree(vblk->vqs); -- 2.25.1 _______________________________________________ Virtualization mailing list Virtualization@xxxxxxxxxxxxxxxxxxxxxxxxxx https://lists.linuxfoundation.org/mailman/listinfo/virtualization