>From 37275d5cfafc87a165824cbf9722ea742a770403 Mon Sep 17 00:00:00 2001
From: Ronnie Sahlberg <[EMAIL PROTECTED]>
Date: Tue, 6 May 2008 16:37:07 +1000
Subject: [PATCH] Fix a memory corruption bug in build_mode_page

If an application is providing a small allocation size when asking for a large
mode page hte memcpy() in build_mode_page can cause memory to be overwritten
and cause a crash.

Signed-off-by: Ronnie Sahlberg <[EMAIL PROTECTED]>
---
 usr/spc.c |   63 ++++++++++++++++++++++++++++++++++--------------------------
 1 files changed, 36 insertions(+), 27 deletions(-)

diff --git a/usr/spc.c b/usr/spc.c
index e3e4d98..35de2e1 100644
--- a/usr/spc.c
+++ b/usr/spc.c
@@ -335,22 +335,28 @@ int spc_test_unit(int host_no, struct scsi_cmd *cmd)
  *
  * Returns number of bytes copied.
  */
-static int build_mode_page(uint8_t *data, struct mode_pg *pg, int update)
+static uint8_t *build_mode_page(uint8_t *data, uint8_t *p, int alloc_len,
+struct mode_pg *pg)
 {
-       uint8_t *p;
-       int len;
+       int i;
+
+       if (alloc_len > (p-data))
+               *p = pg->pcode;
+       p++;
+
+
+       if (alloc_len > (p-data))
+               *p = pg->pcode_size;
+       p++;
+

-       len = pg->pcode_size;
-       if (update) {
-               data[0] = pg->pcode;
-               data[1] = len;
+       for (i = 0; i < pg->pcode_size; i++) {
+               if (alloc_len > (p-data))
+                       *p = pg->mode_data[i];
+               p++;
        }
-       p = &data[2];
-       len += 2;
-       if (update)
-               memcpy(p, pg->mode_data, pg->pcode_size);

-       return len;
+       return p;
 }

 /**
@@ -362,12 +368,13 @@ static int build_mode_page(uint8_t *data, struct
mode_pg *pg, int update)
  */
 int spc_mode_sense(int host_no, struct scsi_cmd *cmd)
 {
-       int len = 0;
        uint8_t *data = NULL, *scb, mode6, dbd, pcode, subpcode;
+       uint8_t *p;
        uint16_t alloc_len;
        unsigned char key = ILLEGAL_REQUEST;
        uint16_t asc = ASC_INVALID_FIELD_IN_CDB;
        struct mode_pg *pg;
+       int i;

        scb = cmd->scb;
        mode6 = (scb[0] == 0x1a);
@@ -383,10 +390,10 @@ int spc_mode_sense(int host_no, struct scsi_cmd *cmd)

        if (mode6) {
                alloc_len = scb[4];
-               len = 4;
+               p = &data[4];
        } else {
                alloc_len = (scb[7] << 8) + scb[8];
-               len = 8;
+               p = &data[8];
        }

        if (scsi_get_in_length(cmd) < alloc_len)
@@ -394,10 +401,11 @@ int spc_mode_sense(int host_no, struct scsi_cmd *cmd)
        memset(data, 0, alloc_len);

        if (!dbd) {
-               if (alloc_len >= len)
-                       memcpy(data + len, cmd->dev->mode_block_descriptor,
-                              BLOCK_DESCRIPTOR_LEN);
-               len += BLOCK_DESCRIPTOR_LEN;
+               for (i = 0; i < BLOCK_DESCRIPTOR_LEN; i++) {
+                       if (alloc_len > (p-data))
+                               *p = cmd->dev->mode_block_descriptor[i];
+                       p++;
+               }
        }

        if (pcode == 0x3f) {
@@ -405,25 +413,26 @@ int spc_mode_sense(int host_no, struct scsi_cmd *cmd)
                for (i = 0; i < ARRAY_SIZE(cmd->dev->mode_pgs); i++) {
                        pg = cmd->dev->mode_pgs[i];
                        if (pg)
-                               len += build_mode_page(data + len, pg,
-                                                      alloc_len >= len);
+                               p = build_mode_page(data, p, alloc_len, pg);
                }
        } else {
                pg = cmd->dev->mode_pgs[pcode];
                if (!pg)
                        goto sense;
-               len += build_mode_page(data + len, pg, alloc_len >= len);
+               p = build_mode_page(data, p, alloc_len, pg);
        }

        if (mode6) {
-               data[0] = len - 1;
-               data[3] = dbd ? 0 : BLOCK_DESCRIPTOR_LEN;
+               data[0] = (p - data) - 1;
+               if (alloc_len > 3)
+                       data[3] = dbd ? 0 : BLOCK_DESCRIPTOR_LEN;
        } else {
-               *(uint16_t *)(data) = __cpu_to_be16(len - 2);
-               data[7] = dbd ? 0 : BLOCK_DESCRIPTOR_LEN;
+               *(uint16_t *)(data) = __cpu_to_be16((p - data)-2);
+               if (alloc_len > 7)
+                       data[7] = dbd ? 0 : BLOCK_DESCRIPTOR_LEN;
        }

-       scsi_set_in_resid_by_actual(cmd, len);
+       scsi_set_in_resid_by_actual(cmd, p - data);
        return SAM_STAT_GOOD;
 sense:
        scsi_set_in_resid_by_actual(cmd, 0);
-- 
1.5.5

Attachment: 0004-Fix-a-memory-corruption-bug-in-build_mode_page.patch.gz
Description: GNU Zip compressed data

_______________________________________________
Stgt-devel mailing list
[email protected]
https://lists.berlios.de/mailman/listinfo/stgt-devel

Reply via email to