aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/s390/scsi
diff options
context:
space:
mode:
authorSteffen Maier <maier@linux.vnet.ibm.com>2012-09-04 09:23:31 -0400
committerJames Bottomley <JBottomley@Parallels.com>2012-09-24 04:11:01 -0400
commit01e60527f0a49b3d7df603010bd6079bb4b6cf07 (patch)
tree5683b67c13a599c43d75f038a341f9dd79c49147 /drivers/s390/scsi
parent0100998dbfe6dfcd90a6e912ca7ed6f255d48f25 (diff)
[SCSI] zfcp: Bounds checking for deferred error trace
The pl vector has scount elements, i.e. pl[scount-1] is the last valid element. For maximum sized requests, payload->counter == scount after the last loop iteration. Therefore, do bounds checking first (with boolean shortcut) to not access the invalid element pl[scount]. Do not trust the maximum sbale->scount value from the HBA but ensure we won't access the pl vector out of our allocated bounds. While at it, clean up scoping and prevent unnecessary memset. Minor fix for 86a9668a8d29ea711613e1cb37efa68e7c4db564 "[SCSI] zfcp: support for hardware data router" Signed-off-by: Steffen Maier <maier@linux.vnet.ibm.com> Reviewed-by: Martin Peschke <mpeschke@linux.vnet.ibm.com> Cc: <stable@vger.kernel.org> #3.2+ Signed-off-by: James Bottomley <JBottomley@Parallels.com>
Diffstat (limited to 'drivers/s390/scsi')
-rw-r--r--drivers/s390/scsi/zfcp_dbf.c2
-rw-r--r--drivers/s390/scsi/zfcp_qdio.c16
2 files changed, 11 insertions, 7 deletions
diff --git a/drivers/s390/scsi/zfcp_dbf.c b/drivers/s390/scsi/zfcp_dbf.c
index 3c1d22097ad0..c6e47d553ad9 100644
--- a/drivers/s390/scsi/zfcp_dbf.c
+++ b/drivers/s390/scsi/zfcp_dbf.c
@@ -191,7 +191,7 @@ void zfcp_dbf_hba_def_err(struct zfcp_adapter *adapter, u64 req_id, u16 scount,
191 length = min((u16)sizeof(struct qdio_buffer), 191 length = min((u16)sizeof(struct qdio_buffer),
192 (u16)ZFCP_DBF_PAY_MAX_REC); 192 (u16)ZFCP_DBF_PAY_MAX_REC);
193 193
194 while ((char *)pl[payload->counter] && payload->counter < scount) { 194 while (payload->counter < scount && (char *)pl[payload->counter]) {
195 memcpy(payload->data, (char *)pl[payload->counter], length); 195 memcpy(payload->data, (char *)pl[payload->counter], length);
196 debug_event(dbf->pay, 1, payload, zfcp_dbf_plen(length)); 196 debug_event(dbf->pay, 1, payload, zfcp_dbf_plen(length));
197 payload->counter++; 197 payload->counter++;
diff --git a/drivers/s390/scsi/zfcp_qdio.c b/drivers/s390/scsi/zfcp_qdio.c
index b9fffc8d94a7..50b5615848f6 100644
--- a/drivers/s390/scsi/zfcp_qdio.c
+++ b/drivers/s390/scsi/zfcp_qdio.c
@@ -102,18 +102,22 @@ static void zfcp_qdio_int_resp(struct ccw_device *cdev, unsigned int qdio_err,
102{ 102{
103 struct zfcp_qdio *qdio = (struct zfcp_qdio *) parm; 103 struct zfcp_qdio *qdio = (struct zfcp_qdio *) parm;
104 struct zfcp_adapter *adapter = qdio->adapter; 104 struct zfcp_adapter *adapter = qdio->adapter;
105 struct qdio_buffer_element *sbale;
106 int sbal_no, sbal_idx; 105 int sbal_no, sbal_idx;
107 void *pl[ZFCP_QDIO_MAX_SBALS_PER_REQ + 1];
108 u64 req_id;
109 u8 scount;
110 106
111 if (unlikely(qdio_err)) { 107 if (unlikely(qdio_err)) {
112 memset(pl, 0, ZFCP_QDIO_MAX_SBALS_PER_REQ * sizeof(void *));
113 if (zfcp_adapter_multi_buffer_active(adapter)) { 108 if (zfcp_adapter_multi_buffer_active(adapter)) {
109 void *pl[ZFCP_QDIO_MAX_SBALS_PER_REQ + 1];
110 struct qdio_buffer_element *sbale;
111 u64 req_id;
112 u8 scount;
113
114 memset(pl, 0,
115 ZFCP_QDIO_MAX_SBALS_PER_REQ * sizeof(void *));
114 sbale = qdio->res_q[idx]->element; 116 sbale = qdio->res_q[idx]->element;
115 req_id = (u64) sbale->addr; 117 req_id = (u64) sbale->addr;
116 scount = sbale->scount + 1; /* incl. signaling SBAL */ 118 scount = min(sbale->scount + 1,
119 ZFCP_QDIO_MAX_SBALS_PER_REQ + 1);
120 /* incl. signaling SBAL */
117 121
118 for (sbal_no = 0; sbal_no < scount; sbal_no++) { 122 for (sbal_no = 0; sbal_no < scount; sbal_no++) {
119 sbal_idx = (idx + sbal_no) % 123 sbal_idx = (idx + sbal_no) %