storvsc: do not assume SG list is continuous when doing bounce buffers The original patch was made for stable 4.1 and was Acked on 08/22/2017, but for some reason it never made it to the stable tree. Change from v1: Changed comment that this patch is for linux-stable 4.1 and all prior stable kernels. storvsc checks the SG list for gaps before passing them to Hyper-v device. If there are gaps, data is copied to a bounce buffer and a continuous data buffer is passed to Hyper-V. The check on gaps assumes SG list is continuous, and not chained. This is not always true. Failing the check may result in incorrect I/O data passed to the Hyper-v device. This code path is not used post Linux 4.1. [LL: Backport for 4.1] Signed-off-by: Long Li <longli@microsoft.com> Acked-by: Martin K. Petersen <martin.petersen@oracle.com> Signed-off-by: Sasha Levin <alexander.levin@microsoft.com>
diff --git a/drivers/scsi/storvsc_drv.c b/drivers/scsi/storvsc_drv.c index e4b103d..98b56a7 100644 --- a/drivers/scsi/storvsc_drv.c +++ b/drivers/scsi/storvsc_drv.c
@@ -582,17 +582,18 @@ for (i = 0; i < sg_count; i++) { if (i == 0) { /* make sure 1st one does not have hole */ - if (sgl[i].offset + sgl[i].length != PAGE_SIZE) + if (sgl->offset + sgl->length != PAGE_SIZE) return i; } else if (i == sg_count - 1) { /* make sure last one does not have hole */ - if (sgl[i].offset != 0) + if (sgl->offset != 0) return i; } else { /* make sure no hole in the middle */ - if (sgl[i].length != PAGE_SIZE || sgl[i].offset != 0) + if (sgl->length != PAGE_SIZE || sgl->offset != 0) return i; } + sgl = sg_next(sgl); } return -1; }