diff options
author | Christoph Hellwig <hch@lst.de> | 2017-01-09 10:56:23 -0500 |
---|---|---|
committer | Jens Axboe <axboe@fb.com> | 2017-01-10 15:30:50 -0500 |
commit | a14d749fcebe97ddf6af6db3d1f6ece85c9ddcb9 (patch) | |
tree | b441577383d9ca1586799d28a031d99e9d6e967d | |
parent | dd545b52a3e1efd9f2c6352dbe95ccd0c53461cc (diff) |
virtio_blk: avoid DMA to stack for the sense buffer
Most users of BLOCK_PC requests allocate the sense buffer on the stack,
so to avoid DMA to the stack copy them to a field in the heap allocated
virtblk_req structure. Without that any attempt at SCSI passthrough I/O,
including the SG_IO ioctl from userspace will crash the kernel. Note that
this includes running tools like hdparm even when the host does not have
SCSI passthrough enabled.
Signed-off-by: Christoph Hellwig <hch@lst.de>
Cc: stable@vger.kernel.org # v4.9+
Signed-off-by: Jens Axboe <axboe@fb.com>
-rw-r--r-- | drivers/block/virtio_blk.c | 4 |
1 files changed, 3 insertions, 1 deletions
diff --git a/drivers/block/virtio_blk.c b/drivers/block/virtio_blk.c index 5545a679abd8..3c3b8f601469 100644 --- a/drivers/block/virtio_blk.c +++ b/drivers/block/virtio_blk.c | |||
@@ -56,6 +56,7 @@ struct virtblk_req { | |||
56 | struct virtio_blk_outhdr out_hdr; | 56 | struct virtio_blk_outhdr out_hdr; |
57 | struct virtio_scsi_inhdr in_hdr; | 57 | struct virtio_scsi_inhdr in_hdr; |
58 | u8 status; | 58 | u8 status; |
59 | u8 sense[SCSI_SENSE_BUFFERSIZE]; | ||
59 | struct scatterlist sg[]; | 60 | struct scatterlist sg[]; |
60 | }; | 61 | }; |
61 | 62 | ||
@@ -102,7 +103,8 @@ static int __virtblk_add_req(struct virtqueue *vq, | |||
102 | } | 103 | } |
103 | 104 | ||
104 | if (type == cpu_to_virtio32(vq->vdev, VIRTIO_BLK_T_SCSI_CMD)) { | 105 | if (type == cpu_to_virtio32(vq->vdev, VIRTIO_BLK_T_SCSI_CMD)) { |
105 | sg_init_one(&sense, vbr->req->sense, SCSI_SENSE_BUFFERSIZE); | 106 | memcpy(vbr->sense, vbr->req->sense, SCSI_SENSE_BUFFERSIZE); |
107 | sg_init_one(&sense, vbr->sense, SCSI_SENSE_BUFFERSIZE); | ||
106 | sgs[num_out + num_in++] = &sense; | 108 | sgs[num_out + num_in++] = &sense; |
107 | sg_init_one(&inhdr, &vbr->in_hdr, sizeof(vbr->in_hdr)); | 109 | sg_init_one(&inhdr, &vbr->in_hdr, sizeof(vbr->in_hdr)); |
108 | sgs[num_out + num_in++] = &inhdr; | 110 | sgs[num_out + num_in++] = &inhdr; |