[stgt] [PATCH 1/4] fix alloc len vs buffer len checks and safeguard memcpy in spc_pr_read_reservation()
nezhinsky at gmail.com
nezhinsky at gmail.com
Sun Dec 23 09:41:12 CET 2012
From: Alexander Nezhinsky <nezhinsky at gmail.com>
SPC-3, 6.13.3.2, alloc len must be at least 8 bytes,
when no reservation is held, additional len field should be 0, total data-in len is 8;
when there is reservation, additional len should be 16, total buffer len is 24.
make sure that setting fields in data-in buffer don't pass its boundary.
Signed-off-by: Alexander Nezhinsky <nezhinsky at gmail.com>
---
usr/spc.c | 43 ++++++++++++++++++++++---------------------
1 file changed, 22 insertions(+), 21 deletions(-)
diff --git a/usr/spc.c b/usr/spc.c
index 9fb5a6d..0289730 100644
--- a/usr/spc.c
+++ b/usr/spc.c
@@ -928,46 +928,47 @@ sense:
static int spc_pr_read_reservation(int host_no, struct scsi_cmd *cmd)
{
- uint16_t asc = ASC_INVALID_FIELD_IN_CDB;
- uint8_t key = ILLEGAL_REQUEST;
+ uint32_t alloc_len, add_len, avail_len, actual_len;
struct registration *reg;
- uint16_t len;
- uint8_t *buf;
uint64_t res_key;
+ uint8_t *buf;
+ uint16_t asc = ASC_INVALID_FIELD_IN_CDB;
+ uint8_t key = ILLEGAL_REQUEST;
- reg = cmd->dev->pr_holder;
-
- if (reg)
- len = 24;
- else
- len = 8;
-
- if (get_unaligned_be16(cmd->scb + 7) < len)
+ alloc_len = (uint32_t)get_unaligned_be16(&cmd->scb[7]);
+ if (alloc_len < 8)
goto sense;
- if (scsi_get_in_length(cmd) < len)
+ if (scsi_get_in_length(cmd) < alloc_len)
goto sense;
+ reg = cmd->dev->pr_holder;
+ add_len = (reg ? 16 : 0);
+ avail_len = 8 + add_len;
+
buf = scsi_get_in_buffer(cmd);
- memset(buf, 0, len);
+ memset(buf, 0, alloc_len);
put_unaligned_be32(cmd->dev->prgeneration, &buf[0]);
+ put_unaligned_be32(add_len, &buf[4]); /* additional length */
if (reg) {
- put_unaligned_be32(16, &buf[4]);
-
if (reg->pr_type == PR_TYPE_WRITE_EXCLUSIVE_ALLREG ||
reg->pr_type == PR_TYPE_EXCLUSIVE_ACCESS_ALLREG)
res_key = 0;
else
res_key = reg->key;
- put_unaligned_be64(res_key, &buf[8]);
- buf[21] = ((reg->pr_scope << 4) & 0xf0) | (reg->pr_type & 0x0f);
- } else
- put_unaligned_be32(0, &buf[4]);
+ if (alloc_len > 15)
+ put_unaligned_be64(res_key, &buf[8]);
+ if (alloc_len > 21) {
+ buf[21] = (reg->pr_scope << 4) & 0xf0;
+ buf[21] |= reg->pr_type & 0x0f;
+ }
+ }
- scsi_set_in_resid_by_actual(cmd, len);
+ actual_len = min_t(uint32_t, alloc_len, avail_len);
+ scsi_set_in_resid_by_actual(cmd, actual_len);
return SAM_STAT_GOOD;
sense:
--
1.7.9.6
--
To unsubscribe from this list: send the line "unsubscribe stgt" in
the body of a message to majordomo at vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
More information about the stgt
mailing list