aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/target/target_core_alua.c
diff options
context:
space:
mode:
authorNicholas Bellinger <nab@linux-iscsi.org>2011-10-19 02:48:04 -0400
committerNicholas Bellinger <nab@linux-iscsi.org>2011-10-23 23:21:19 -0400
commit6b20fa9aaf0c2f69ee6f9648e20ab2be0206705e (patch)
tree468f2d3ed5583cf31c3718dd5c15902676e527c7 /drivers/target/target_core_alua.c
parentb937d27052e5759b1308782166fe47bc76e05b4d (diff)
target: Fix REPORT TARGET PORT GROUPS handling with small allocation length
This patch fixes a bug with the handling of REPORT TARGET PORT GROUPS containing a smaller allocation length than the payload requires causing memory writes beyond the end of the buffer. This patch checks for the minimum 4 byte length for the response payload length, and also checks upon each loop of T10_ALUA(su_dev)->tg_pt_gps_list to ensure the Target port group and Target port descriptor list is able to fit into the remaining allocation length. If the response payload exceeds the allocation length length, then rd_len is still increments to indicate to the initiator that the payload has been truncated. Reported-by: Roland Dreier <roland@purestorage.com> Cc: stable@kernel.org Signed-off-by: Nicholas Bellinger <nab@risingtidesystems.com>
Diffstat (limited to 'drivers/target/target_core_alua.c')
-rw-r--r--drivers/target/target_core_alua.c20
1 files changed, 20 insertions, 0 deletions
diff --git a/drivers/target/target_core_alua.c b/drivers/target/target_core_alua.c
index 007c6c298b8b..8f4447749c71 100644
--- a/drivers/target/target_core_alua.c
+++ b/drivers/target/target_core_alua.c
@@ -67,6 +67,15 @@ int core_emulate_report_target_port_groups(struct se_cmd *cmd)
67 unsigned char *buf; 67 unsigned char *buf;
68 u32 rd_len = 0, off = 4; /* Skip over RESERVED area to first 68 u32 rd_len = 0, off = 4; /* Skip over RESERVED area to first
69 Target port group descriptor */ 69 Target port group descriptor */
70 /*
71 * Need at least 4 bytes of response data or else we can't
72 * even fit the return data length.
73 */
74 if (cmd->data_length < 4) {
75 pr_warn("REPORT TARGET PORT GROUPS allocation length %u"
76 " too small\n", cmd->data_length);
77 return -EINVAL;
78 }
70 79
71 buf = transport_kmap_first_data_page(cmd); 80 buf = transport_kmap_first_data_page(cmd);
72 81
@@ -74,6 +83,17 @@ int core_emulate_report_target_port_groups(struct se_cmd *cmd)
74 list_for_each_entry(tg_pt_gp, &su_dev->t10_alua.tg_pt_gps_list, 83 list_for_each_entry(tg_pt_gp, &su_dev->t10_alua.tg_pt_gps_list,
75 tg_pt_gp_list) { 84 tg_pt_gp_list) {
76 /* 85 /*
86 * Check if the Target port group and Target port descriptor list
87 * based on tg_pt_gp_members count will fit into the response payload.
88 * Otherwise, bump rd_len to let the initiator know we have exceeded
89 * the allocation length and the response is truncated.
90 */
91 if ((off + 8 + (tg_pt_gp->tg_pt_gp_members * 4)) >
92 cmd->data_length) {
93 rd_len += 8 + (tg_pt_gp->tg_pt_gp_members * 4);
94 continue;
95 }
96 /*
77 * PREF: Preferred target port bit, determine if this 97 * PREF: Preferred target port bit, determine if this
78 * bit should be set for port group. 98 * bit should be set for port group.
79 */ 99 */