Blame 0048-scsi-Allocate-SCSITargetReq-r-buf-dynamically.patch

298366
From fdcbe7d587a64dec0db0d3c9a3b230c39efbfeef Mon Sep 17 00:00:00 2001
298366
From: Asias He <asias@redhat.com>
298366
Date: Fri, 13 Sep 2013 14:56:55 +0800
298366
Subject: [PATCH] scsi: Allocate SCSITargetReq r->buf dynamically
298366
298366
BZ: https://bugzilla.redhat.com/show_bug.cgi?id=1007330
298366
Brew: https://brewweb.devel.redhat.com/taskinfo?taskID=6282465
298366
298366
This is the backport of the following commit. The patch is not
298366
sent public since it is a embargoed bug.
298366
298366
   r->buf is hardcoded to 2056 which is (256 + 1) * 8, allowing 256 luns at
298366
   most. If more than 256 luns are specified by user, we have buffer
298366
   overflow in scsi_target_emulate_report_luns.
298366
298366
   To fix, we allocate the buffer dynamically.
298366
298366
   Signed-off-by: Asias He <asias@redhat.com>
298366
298366
Signed-off-by: Asias He <asias@redhat.com>
298366
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
298366
298366
*s/&r->buf/r->buf/ due to type change
298366
298366
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
298366
---
298366
 hw/scsi/scsi-bus.c     | 44 +++++++++++++++++++++++++++++++++-----------
298366
 include/hw/scsi/scsi.h |  2 ++
298366
 2 files changed, 35 insertions(+), 11 deletions(-)
298366
298366
diff --git a/hw/scsi/scsi-bus.c b/hw/scsi/scsi-bus.c
298366
index 8fe4f4c..ad26c25 100644
298366
--- a/hw/scsi/scsi-bus.c
298366
+++ b/hw/scsi/scsi-bus.c
298366
@@ -11,6 +11,8 @@ static char *scsibus_get_dev_path(DeviceState *dev);
298366
 static char *scsibus_get_fw_dev_path(DeviceState *dev);
298366
 static int scsi_req_parse(SCSICommand *cmd, SCSIDevice *dev, uint8_t *buf);
298366
 static void scsi_req_dequeue(SCSIRequest *req);
298366
+static uint8_t *scsi_target_alloc_buf(SCSIRequest *req, size_t len);
298366
+static void scsi_target_free_buf(SCSIRequest *req);
298366
 
298366
 static Property scsi_props[] = {
298366
     DEFINE_PROP_UINT32("channel", SCSIDevice, channel, 0),
298366
@@ -317,7 +319,8 @@ typedef struct SCSITargetReq SCSITargetReq;
298366
 struct SCSITargetReq {
298366
     SCSIRequest req;
298366
     int len;
298366
-    uint8_t buf[2056];
298366
+    uint8_t *buf;
298366
+    int buf_len;
298366
 };
298366
 
298366
 static void store_lun(uint8_t *outbuf, int lun)
298366
@@ -361,14 +364,12 @@ static bool scsi_target_emulate_report_luns(SCSITargetReq *r)
298366
     if (!found_lun0) {
298366
         n += 8;
298366
     }
298366
-    len = MIN(n + 8, r->req.cmd.xfer & ~7);
298366
-    if (len > sizeof(r->buf)) {
298366
-        /* TODO: > 256 LUNs? */
298366
-        return false;
298366
-    }
298366
 
298366
+    scsi_target_alloc_buf(&r->req, n + 8);
298366
+
298366
+    len = MIN(n + 8, r->req.cmd.xfer & ~7);
298366
     memset(r->buf, 0, len);
298366
-    stl_be_p(&r->buf, n);
298366
+    stl_be_p(r->buf, n);
298366
     i = found_lun0 ? 8 : 16;
298366
     QTAILQ_FOREACH(kid, &r->req.bus->qbus.children, sibling) {
298366
         DeviceState *qdev = kid->child;
298366
@@ -387,6 +388,9 @@ static bool scsi_target_emulate_report_luns(SCSITargetReq *r)
298366
 static bool scsi_target_emulate_inquiry(SCSITargetReq *r)
298366
 {
298366
     assert(r->req.dev->lun != r->req.lun);
298366
+
298366
+    scsi_target_alloc_buf(&r->req, SCSI_INQUIRY_LEN);
298366
+
298366
     if (r->req.cmd.buf[1] & 0x2) {
298366
         /* Command support data - optional, not implemented */
298366
         return false;
298366
@@ -411,7 +415,7 @@ static bool scsi_target_emulate_inquiry(SCSITargetReq *r)
298366
             return false;
298366
         }
298366
         /* done with EVPD */
298366
-        assert(r->len < sizeof(r->buf));
298366
+        assert(r->len < r->buf_len);
298366
         r->len = MIN(r->req.cmd.xfer, r->len);
298366
         return true;
298366
     }
298366
@@ -455,8 +459,8 @@ static int32_t scsi_target_send_command(SCSIRequest *req, uint8_t *buf)
298366
         }
298366
         break;
298366
     case REQUEST_SENSE:
298366
-        r->len = scsi_device_get_sense(r->req.dev, r->buf,
298366
-                                       MIN(req->cmd.xfer, sizeof r->buf),
298366
+        scsi_target_alloc_buf(&r->req, SCSI_SENSE_LEN);
298366
+        r->len = scsi_device_get_sense(r->req.dev, r->buf, r->buf_len,
298366
                                        (req->cmd.buf[1] & 1) == 0);
298366
         if (r->req.dev->sense_is_ua) {
298366
             scsi_device_unit_attention_reported(req->dev);
298366
@@ -501,11 +505,29 @@ static uint8_t *scsi_target_get_buf(SCSIRequest *req)
298366
     return r->buf;
298366
 }
298366
 
298366
+static uint8_t *scsi_target_alloc_buf(SCSIRequest *req, size_t len)
298366
+{
298366
+    SCSITargetReq *r = DO_UPCAST(SCSITargetReq, req, req);
298366
+
298366
+    r->buf = g_malloc(len);
298366
+    r->buf_len = len;
298366
+
298366
+    return r->buf;
298366
+}
298366
+
298366
+static void scsi_target_free_buf(SCSIRequest *req)
298366
+{
298366
+    SCSITargetReq *r = DO_UPCAST(SCSITargetReq, req, req);
298366
+
298366
+    g_free(r->buf);
298366
+}
298366
+
298366
 static const struct SCSIReqOps reqops_target_command = {
298366
     .size         = sizeof(SCSITargetReq),
298366
     .send_command = scsi_target_send_command,
298366
     .read_data    = scsi_target_read_data,
298366
     .get_buf      = scsi_target_get_buf,
298366
+    .free_req     = scsi_target_free_buf,
298366
 };
298366
 
298366
 
298366
@@ -1365,7 +1387,7 @@ int scsi_build_sense(uint8_t *in_buf, int in_len,
298366
         buf[7] = 10;
298366
         buf[12] = sense.asc;
298366
         buf[13] = sense.ascq;
298366
-        return MIN(len, 18);
298366
+        return MIN(len, SCSI_SENSE_LEN);
298366
     } else {
298366
         /* Return descriptor format sense buffer */
298366
         buf[0] = 0x72;
298366
diff --git a/include/hw/scsi/scsi.h b/include/hw/scsi/scsi.h
298366
index 8786531..18cb694 100644
298366
--- a/include/hw/scsi/scsi.h
298366
+++ b/include/hw/scsi/scsi.h
298366
@@ -9,6 +9,8 @@
298366
 #define MAX_SCSI_DEVS	255
298366
 
298366
 #define SCSI_CMD_BUF_SIZE     16
298366
+#define SCSI_SENSE_LEN      18
298366
+#define SCSI_INQUIRY_LEN    36
298366
 
298366
 typedef struct SCSIBus SCSIBus;
298366
 typedef struct SCSIBusInfo SCSIBusInfo;