qemu-devel
[Top][All Lists]
Advanced

[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




reply via email to

[Prev in Thread] Current Thread [Next in Thread]