diff options
author | Ralph Campbell <ralph.campbell@qlogic.com> | 2007-06-18 17:24:44 -0400 |
---|---|---|
committer | Roland Dreier <rolandd@cisco.com> | 2007-07-09 23:12:26 -0400 |
commit | 30d149ab58cc3ed8e4bc9c4dc45bebbed0e84b6e (patch) | |
tree | f85f47458efb9e98f01b490a539dbf873bbaddd9 /drivers/infiniband/hw/ipath | |
parent | db5518cd09c21f0fa70af0a4ca38badd90622c9e (diff) |
IB/ipath: Fix possible data corruption if multiple SGEs used for receive
The code to copy data from the receive queue buffers to the IB SGEs
doesn't check the SGE length, only the memory region/page length when
copying data. This could overwrite parts of the user's memory that
were not intended to be written. It can only happen if multiple SGEs
are used to describe a receive buffer which almost never happens in
practice.
Signed-off-by: Ralph Campbell <ralph.campbell@qlogic.com>
Signed-off-by: Roland Dreier <rolandd@cisco.com>
Diffstat (limited to 'drivers/infiniband/hw/ipath')
-rw-r--r-- | drivers/infiniband/hw/ipath/ipath_ruc.c | 2 | ||||
-rw-r--r-- | drivers/infiniband/hw/ipath/ipath_ud.c | 2 | ||||
-rw-r--r-- | drivers/infiniband/hw/ipath/ipath_verbs.c | 8 |
3 files changed, 10 insertions, 2 deletions
diff --git a/drivers/infiniband/hw/ipath/ipath_ruc.c b/drivers/infiniband/hw/ipath/ipath_ruc.c index 837118676cc7..1b0e62b761bb 100644 --- a/drivers/infiniband/hw/ipath/ipath_ruc.c +++ b/drivers/infiniband/hw/ipath/ipath_ruc.c | |||
@@ -396,6 +396,8 @@ again: | |||
396 | 396 | ||
397 | if (len > sge->length) | 397 | if (len > sge->length) |
398 | len = sge->length; | 398 | len = sge->length; |
399 | if (len > sge->sge_length) | ||
400 | len = sge->sge_length; | ||
399 | BUG_ON(len == 0); | 401 | BUG_ON(len == 0); |
400 | ipath_copy_sge(&qp->r_sge, sge->vaddr, len); | 402 | ipath_copy_sge(&qp->r_sge, sge->vaddr, len); |
401 | sge->vaddr += len; | 403 | sge->vaddr += len; |
diff --git a/drivers/infiniband/hw/ipath/ipath_ud.c b/drivers/infiniband/hw/ipath/ipath_ud.c index a518f7c8fa83..0b5a6ac1bb83 100644 --- a/drivers/infiniband/hw/ipath/ipath_ud.c +++ b/drivers/infiniband/hw/ipath/ipath_ud.c | |||
@@ -231,6 +231,8 @@ static void ipath_ud_loopback(struct ipath_qp *sqp, | |||
231 | 231 | ||
232 | if (len > length) | 232 | if (len > length) |
233 | len = length; | 233 | len = length; |
234 | if (len > sge->sge_length) | ||
235 | len = sge->sge_length; | ||
234 | BUG_ON(len == 0); | 236 | BUG_ON(len == 0); |
235 | ipath_copy_sge(&rsge, sge->vaddr, len); | 237 | ipath_copy_sge(&rsge, sge->vaddr, len); |
236 | sge->vaddr += len; | 238 | sge->vaddr += len; |
diff --git a/drivers/infiniband/hw/ipath/ipath_verbs.c b/drivers/infiniband/hw/ipath/ipath_verbs.c index cd79a8ca5104..35241b76d766 100644 --- a/drivers/infiniband/hw/ipath/ipath_verbs.c +++ b/drivers/infiniband/hw/ipath/ipath_verbs.c | |||
@@ -164,9 +164,11 @@ void ipath_copy_sge(struct ipath_sge_state *ss, void *data, u32 length) | |||
164 | while (length) { | 164 | while (length) { |
165 | u32 len = sge->length; | 165 | u32 len = sge->length; |
166 | 166 | ||
167 | BUG_ON(len == 0); | ||
168 | if (len > length) | 167 | if (len > length) |
169 | len = length; | 168 | len = length; |
169 | if (len > sge->sge_length) | ||
170 | len = sge->sge_length; | ||
171 | BUG_ON(len == 0); | ||
170 | memcpy(sge->vaddr, data, len); | 172 | memcpy(sge->vaddr, data, len); |
171 | sge->vaddr += len; | 173 | sge->vaddr += len; |
172 | sge->length -= len; | 174 | sge->length -= len; |
@@ -202,9 +204,11 @@ void ipath_skip_sge(struct ipath_sge_state *ss, u32 length) | |||
202 | while (length) { | 204 | while (length) { |
203 | u32 len = sge->length; | 205 | u32 len = sge->length; |
204 | 206 | ||
205 | BUG_ON(len == 0); | ||
206 | if (len > length) | 207 | if (len > length) |
207 | len = length; | 208 | len = length; |
209 | if (len > sge->sge_length) | ||
210 | len = sge->sge_length; | ||
211 | BUG_ON(len == 0); | ||
208 | sge->vaddr += len; | 212 | sge->vaddr += len; |
209 | sge->length -= len; | 213 | sge->length -= len; |
210 | sge->sge_length -= len; | 214 | sge->sge_length -= len; |