On 05/03/20 09:31, Philippe Mathieu-Daudé wrote:
> This series fixes a dangerous zero-length array use.
> Simples patches first to clean the issue in the last patch:
> dissociate the buffer holding DMA requests with pointer to
> SRP Information Unit packets.
>
> v2: Addressed David Gibson review comments
>
> Philippe Mathieu-Daudé (5):
> hw/scsi/viosrp: Add missing 'hw/scsi/srp.h' include
> hw/scsi/spapr_vscsi: Use SRP_MAX_IU_LEN instead of sizeof flexible
> array
> hw/scsi/spapr_vscsi: Simplify a bit
> hw/scsi/spapr_vscsi: Introduce req_iu() helper
> hw/scsi/spapr_vscsi: Do not mix SRP IU size with DMA buffer size
>
> hw/scsi/viosrp.h | 3 ++-
> hw/scsi/spapr_vscsi.c | 59 ++++++++++++++++++++++++-------------------
> 2 files changed, 35 insertions(+), 27 deletions(-)
>
I think this is clearer than the "reserved" member, and it gets one
important thing right though by decoupling SRP_MAX_IU_LEN from
sizeof(union srp_iu).
However it doesn't fix the actual time bomb, which is that,
vscsi_send_rsp can overrun the buffer size here depending on the length
of sense data:
memcpy(req->iu.srp.rsp.data, req->sense, req->senselen);
But with this series in place we can fix that with just a couple of
asserts, like this:
/* This #define is why Phil's changes matter! */
#define SRP_MAX_IU_DATA_LEN (SRP_MAX_IU_LEN - sizeof(union srp_iu))
/* in vscsi_send_rsp */
int sense_data_len = MIN(req->senselen, SRP_MAX_IU_DATA_LEN);
req->iu.srp.rsp.sense_data_len = cpu_to_be32(sense_data_len);
memcpy(req->iu.srp.rsp.data, req->sense, sense_data_len);
/* in vscsi_send_iu */
assert(length < SRP_MAX_IU_LEN);
/* in vscsi_process_tsk_mgmt */
QEMU_BUILD_BUG_ON(SRP_MAX_IU_DATA_LEN < 4);
(Easier to write code than describe...).
Paolo