提交 30d149ab 编写于 作者: R Ralph Campbell 提交者: Roland Dreier

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: NRalph Campbell <ralph.campbell@qlogic.com>
Signed-off-by: NRoland Dreier <rolandd@cisco.com>
上级 db5518cd
...@@ -396,6 +396,8 @@ static void ipath_ruc_loopback(struct ipath_qp *sqp) ...@@ -396,6 +396,8 @@ static void ipath_ruc_loopback(struct ipath_qp *sqp)
if (len > sge->length) if (len > sge->length)
len = sge->length; len = sge->length;
if (len > sge->sge_length)
len = sge->sge_length;
BUG_ON(len == 0); BUG_ON(len == 0);
ipath_copy_sge(&qp->r_sge, sge->vaddr, len); ipath_copy_sge(&qp->r_sge, sge->vaddr, len);
sge->vaddr += len; sge->vaddr += len;
......
...@@ -231,6 +231,8 @@ static void ipath_ud_loopback(struct ipath_qp *sqp, ...@@ -231,6 +231,8 @@ static void ipath_ud_loopback(struct ipath_qp *sqp,
if (len > length) if (len > length)
len = length; len = length;
if (len > sge->sge_length)
len = sge->sge_length;
BUG_ON(len == 0); BUG_ON(len == 0);
ipath_copy_sge(&rsge, sge->vaddr, len); ipath_copy_sge(&rsge, sge->vaddr, len);
sge->vaddr += len; sge->vaddr += len;
......
...@@ -164,9 +164,11 @@ void ipath_copy_sge(struct ipath_sge_state *ss, void *data, u32 length) ...@@ -164,9 +164,11 @@ void ipath_copy_sge(struct ipath_sge_state *ss, void *data, u32 length)
while (length) { while (length) {
u32 len = sge->length; u32 len = sge->length;
BUG_ON(len == 0);
if (len > length) if (len > length)
len = length; len = length;
if (len > sge->sge_length)
len = sge->sge_length;
BUG_ON(len == 0);
memcpy(sge->vaddr, data, len); memcpy(sge->vaddr, data, len);
sge->vaddr += len; sge->vaddr += len;
sge->length -= len; sge->length -= len;
...@@ -202,9 +204,11 @@ void ipath_skip_sge(struct ipath_sge_state *ss, u32 length) ...@@ -202,9 +204,11 @@ void ipath_skip_sge(struct ipath_sge_state *ss, u32 length)
while (length) { while (length) {
u32 len = sge->length; u32 len = sge->length;
BUG_ON(len == 0);
if (len > length) if (len > length)
len = length; len = length;
if (len > sge->sge_length)
len = sge->sge_length;
BUG_ON(len == 0);
sge->vaddr += len; sge->vaddr += len;
sge->length -= len; sge->length -= len;
sge->sge_length -= len; sge->sge_length -= len;
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册