From 13a5490536c5c260ad158d5b9672daebcd1d85d5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= Date: Thu, 5 Mar 2020 13:12:52 +0100 Subject: hw/scsi/spapr_vscsi: Prevent buffer overflow MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Depending on the length of sense data, vscsi_send_rsp() can overrun the buffer size. Do not copy more than SRP_MAX_IU_DATA_LEN bytes, and assert that vscsi_send_iu() is always called with a size in range. Reported-by: Paolo Bonzini Suggested-by: Paolo Bonzini Signed-off-by: Philippe Mathieu-Daudé Message-Id: <20200305121253.19078-7-philmd@redhat.com> Reviewed-by: Paolo Bonzini Signed-off-by: David Gibson --- hw/scsi/spapr_vscsi.c | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/hw/scsi/spapr_vscsi.c b/hw/scsi/spapr_vscsi.c index acf9bb5..c4c4f31 100644 --- a/hw/scsi/spapr_vscsi.c +++ b/hw/scsi/spapr_vscsi.c @@ -55,6 +55,8 @@ #define VSCSI_MAX_SECTORS 4096 #define VSCSI_REQ_LIMIT 24 +/* Maximum size of a IU payload */ +#define SRP_MAX_IU_DATA_LEN (SRP_MAX_IU_LEN - sizeof(union srp_iu)) #define SRP_RSP_SENSE_DATA_LEN 18 #define SRP_REPORT_LUNS_WLUN 0xc10100000000000ULL @@ -181,6 +183,8 @@ static int vscsi_send_iu(VSCSIState *s, vscsi_req *req, { long rc, rc1; + assert(length <= SRP_MAX_IU_LEN); + /* First copy the SRP */ rc = spapr_vio_dma_write(&s->vdev, req->crq.s.IU_data_ptr, &req->viosrp_iu_buf, length); @@ -266,10 +270,12 @@ static int vscsi_send_rsp(VSCSIState *s, vscsi_req *req, if (status) { iu->srp.rsp.sol_not = (sol_not & 0x04) >> 2; if (req->senselen) { + int sense_data_len = MIN(req->senselen, SRP_MAX_IU_DATA_LEN); + iu->srp.rsp.flags |= SRP_RSP_FLAG_SNSVALID; - iu->srp.rsp.sense_data_len = cpu_to_be32(req->senselen); - memcpy(iu->srp.rsp.data, req->sense, req->senselen); - total_len += req->senselen; + iu->srp.rsp.sense_data_len = cpu_to_be32(sense_data_len); + memcpy(iu->srp.rsp.data, req->sense, sense_data_len); + total_len += sense_data_len; } } else { iu->srp.rsp.sol_not = (sol_not & 0x02) >> 1; @@ -896,6 +902,7 @@ static int vscsi_process_tsk_mgmt(VSCSIState *s, vscsi_req *req) } /* Compose the response here as */ + QEMU_BUILD_BUG_ON(SRP_MAX_IU_DATA_LEN < 4); memset(iu, 0, sizeof(struct srp_rsp) + 4); iu->srp.rsp.opcode = SRP_RSP; iu->srp.rsp.req_lim_delta = cpu_to_be32(1); -- cgit v1.1