target_core_alua: check for buffer overflow
authorHannes Reinecke <hare@suse.de>
Thu, 19 Dec 2013 13:36:11 +0000 (14:36 +0100)
committerNicholas Bellinger <nab@linux-iscsi.org>
Fri, 10 Jan 2014 05:48:38 +0000 (21:48 -0800)
When a writing to a command-provided buffer we need to ensure
that we're not writing past the end of it.
At the same time we need to continue processing as typically
the final data length (ie the required size of the buffer)
need to be returned.

Signed-off-by: Hannes Reinecke <hare@suse.de>
Signed-off-by: Nicholas Bellinger <nab@linux-iscsi.org>
drivers/target/target_core_alua.c

index e73edcad7930f4868f50a79b9518d621976fdf33..12da9b386169b7ece6150387777bf467426dc42e 100644 (file)
@@ -96,22 +96,33 @@ target_emulate_report_referrals(struct se_cmd *cmd)
                int pg_num;
 
                off += 4;
-               put_unaligned_be64(map->lba_map_first_lba, &buf[off]);
+               if (cmd->data_length > off)
+                       put_unaligned_be64(map->lba_map_first_lba, &buf[off]);
                off += 8;
-               put_unaligned_be64(map->lba_map_last_lba, &buf[off]);
+               if (cmd->data_length > off)
+                       put_unaligned_be64(map->lba_map_last_lba, &buf[off]);
                off += 8;
                rd_len += 20;
                pg_num = 0;
                list_for_each_entry(map_mem, &map->lba_map_mem_list,
                                    lba_map_mem_list) {
-                       buf[off++] = map_mem->lba_map_mem_alua_state & 0x0f;
+                       int alua_state = map_mem->lba_map_mem_alua_state;
+                       int alua_pg_id = map_mem->lba_map_mem_alua_pg_id;
+
+                       if (cmd->data_length > off)
+                               buf[off] = alua_state & 0x0f;
+                       off += 2;
+                       if (cmd->data_length > off)
+                               buf[off] = (alua_pg_id >> 8) & 0xff;
+                       off++;
+                       if (cmd->data_length > off)
+                               buf[off] = (alua_pg_id & 0xff);
                        off++;
-                       buf[off++] = (map_mem->lba_map_mem_alua_pg_id >> 8) & 0xff;
-                       buf[off++] = (map_mem->lba_map_mem_alua_pg_id & 0xff);
                        rd_len += 4;
                        pg_num++;
                }
-               buf[desc_num] = pg_num;
+               if (cmd->data_length > desc_num)
+                       buf[desc_num] = pg_num;
        }
        spin_unlock(&dev->t10_alua.lba_map_lock);