[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: [Qemu-devel] [PATCH] scsi: Allocate SCSITargetReq r->buf dynamically
From: |
Michael Roth |
Subject: |
Re: [Qemu-devel] [PATCH] scsi: Allocate SCSITargetReq r->buf dynamically |
Date: |
Tue, 08 Oct 2013 15:57:59 -0500 |
User-agent: |
alot/0.3.4 |
Quoting Asias He (2013-10-08 03:43:37)
> r->buf is hardcoded to 2056 which is (256 + 1) * 8, allowing 256 luns at
> most. If more than 256 luns are specified by user, we have buffer
> overflow in scsi_target_emulate_report_luns.
>
> To fix, we allocate the buffer dynamically.
>
> Signed-off-by: Asias He <address@hidden>
Tested-by: Michael Roth <address@hidden>
> ---
> hw/scsi/scsi-bus.c | 44 +++++++++++++++++++++++++++++++++-----------
> include/hw/scsi/scsi.h | 2 ++
> 2 files changed, 35 insertions(+), 11 deletions(-)
>
> diff --git a/hw/scsi/scsi-bus.c b/hw/scsi/scsi-bus.c
> index 4d36841..d950e6f 100644
> --- a/hw/scsi/scsi-bus.c
> +++ b/hw/scsi/scsi-bus.c
> @@ -11,6 +11,8 @@ static char *scsibus_get_dev_path(DeviceState *dev);
> static char *scsibus_get_fw_dev_path(DeviceState *dev);
> static int scsi_req_parse(SCSICommand *cmd, SCSIDevice *dev, uint8_t *buf);
> static void scsi_req_dequeue(SCSIRequest *req);
> +static uint8_t *scsi_target_alloc_buf(SCSIRequest *req, size_t len);
> +static void scsi_target_free_buf(SCSIRequest *req);
>
> static Property scsi_props[] = {
> DEFINE_PROP_UINT32("channel", SCSIDevice, channel, 0),
> @@ -317,7 +319,8 @@ typedef struct SCSITargetReq SCSITargetReq;
> struct SCSITargetReq {
> SCSIRequest req;
> int len;
> - uint8_t buf[2056];
> + uint8_t *buf;
> + int buf_len;
> };
>
> static void store_lun(uint8_t *outbuf, int lun)
> @@ -361,14 +364,12 @@ static bool
> scsi_target_emulate_report_luns(SCSITargetReq *r)
> if (!found_lun0) {
> n += 8;
> }
> - len = MIN(n + 8, r->req.cmd.xfer & ~7);
> - if (len > sizeof(r->buf)) {
> - /* TODO: > 256 LUNs? */
> - return false;
> - }
>
> + scsi_target_alloc_buf(&r->req, n + 8);
> +
> + len = MIN(n + 8, r->req.cmd.xfer & ~7);
> memset(r->buf, 0, len);
> - stl_be_p(&r->buf, n);
> + stl_be_p(&r->buf[0], n);
> i = found_lun0 ? 8 : 16;
> QTAILQ_FOREACH(kid, &r->req.bus->qbus.children, sibling) {
> DeviceState *qdev = kid->child;
> @@ -387,6 +388,9 @@ static bool scsi_target_emulate_report_luns(SCSITargetReq
> *r)
> static bool scsi_target_emulate_inquiry(SCSITargetReq *r)
> {
> assert(r->req.dev->lun != r->req.lun);
> +
> + scsi_target_alloc_buf(&r->req, SCSI_INQUIRY_LEN);
> +
> if (r->req.cmd.buf[1] & 0x2) {
> /* Command support data - optional, not implemented */
> return false;
> @@ -411,7 +415,7 @@ static bool scsi_target_emulate_inquiry(SCSITargetReq *r)
> return false;
> }
> /* done with EVPD */
> - assert(r->len < sizeof(r->buf));
> + assert(r->len < r->buf_len);
> r->len = MIN(r->req.cmd.xfer, r->len);
> return true;
> }
> @@ -455,8 +459,8 @@ static int32_t scsi_target_send_command(SCSIRequest *req,
> uint8_t *buf)
> }
> break;
> case REQUEST_SENSE:
> - r->len = scsi_device_get_sense(r->req.dev, r->buf,
> - MIN(req->cmd.xfer, sizeof r->buf),
> + scsi_target_alloc_buf(&r->req, SCSI_SENSE_LEN);
> + r->len = scsi_device_get_sense(r->req.dev, r->buf, r->buf_len,
> (req->cmd.buf[1] & 1) == 0);
> if (r->req.dev->sense_is_ua) {
> scsi_device_unit_attention_reported(req->dev);
> @@ -501,11 +505,29 @@ static uint8_t *scsi_target_get_buf(SCSIRequest *req)
> return r->buf;
> }
>
> +static uint8_t *scsi_target_alloc_buf(SCSIRequest *req, size_t len)
> +{
> + SCSITargetReq *r = DO_UPCAST(SCSITargetReq, req, req);
> +
> + r->buf = g_malloc(len);
> + r->buf_len = len;
> +
> + return r->buf;
> +}
> +
> +static void scsi_target_free_buf(SCSIRequest *req)
> +{
> + SCSITargetReq *r = DO_UPCAST(SCSITargetReq, req, req);
> +
> + g_free(r->buf);
> +}
> +
> static const struct SCSIReqOps reqops_target_command = {
> .size = sizeof(SCSITargetReq),
> .send_command = scsi_target_send_command,
> .read_data = scsi_target_read_data,
> .get_buf = scsi_target_get_buf,
> + .free_req = scsi_target_free_buf,
> };
>
>
> @@ -1365,7 +1387,7 @@ int scsi_build_sense(uint8_t *in_buf, int in_len,
> buf[7] = 10;
> buf[12] = sense.asc;
> buf[13] = sense.ascq;
> - return MIN(len, 18);
> + return MIN(len, SCSI_SENSE_LEN);
> } else {
> /* Return descriptor format sense buffer */
> buf[0] = 0x72;
> diff --git a/include/hw/scsi/scsi.h b/include/hw/scsi/scsi.h
> index 1b66510..76f6ac2 100644
> --- a/include/hw/scsi/scsi.h
> +++ b/include/hw/scsi/scsi.h
> @@ -9,6 +9,8 @@
> #define MAX_SCSI_DEVS 255
>
> #define SCSI_CMD_BUF_SIZE 16
> +#define SCSI_SENSE_LEN 18
> +#define SCSI_INQUIRY_LEN 36
>
> typedef struct SCSIBus SCSIBus;
> typedef struct SCSIBusInfo SCSIBusInfo;
> --
> 1.8.3.1