Commit 147280d8 authored by James Simmons's avatar James Simmons Committed by Greg Kroah-Hartman

staging: lustre: ko2iblnd: fix memory corruption with fragments

In my test of the upstream client this change exposed a long
standing issues where we have a offset that is not page algined
would causes us to access memory beyond the scatter gather list
which was causing memory corruption when all 256 fragments were
in use.
Signed-off-by: default avatarJames Simmons <jsimmons@infradead.org>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent cd779f2e
...@@ -2011,8 +2011,8 @@ static void kiblnd_destroy_tx_pool(kib_pool_t *pool) ...@@ -2011,8 +2011,8 @@ static void kiblnd_destroy_tx_pool(kib_pool_t *pool)
sizeof(*tx->tx_pages)); sizeof(*tx->tx_pages));
if (tx->tx_frags) if (tx->tx_frags)
LIBCFS_FREE(tx->tx_frags, LIBCFS_FREE(tx->tx_frags,
IBLND_MAX_RDMA_FRAGS * (1 + IBLND_MAX_RDMA_FRAGS) *
sizeof(*tx->tx_frags)); sizeof(*tx->tx_frags));
if (tx->tx_wrq) if (tx->tx_wrq)
LIBCFS_FREE(tx->tx_wrq, LIBCFS_FREE(tx->tx_wrq,
(1 + IBLND_MAX_RDMA_FRAGS) * (1 + IBLND_MAX_RDMA_FRAGS) *
...@@ -2090,11 +2090,12 @@ static int kiblnd_create_tx_pool(kib_poolset_t *ps, int size, ...@@ -2090,11 +2090,12 @@ static int kiblnd_create_tx_pool(kib_poolset_t *ps, int size,
} }
LIBCFS_CPT_ALLOC(tx->tx_frags, lnet_cpt_table(), ps->ps_cpt, LIBCFS_CPT_ALLOC(tx->tx_frags, lnet_cpt_table(), ps->ps_cpt,
IBLND_MAX_RDMA_FRAGS * sizeof(*tx->tx_frags)); (1 + IBLND_MAX_RDMA_FRAGS) *
sizeof(*tx->tx_frags));
if (!tx->tx_frags) if (!tx->tx_frags)
break; break;
sg_init_table(tx->tx_frags, IBLND_MAX_RDMA_FRAGS); sg_init_table(tx->tx_frags, IBLND_MAX_RDMA_FRAGS + 1);
LIBCFS_CPT_ALLOC(tx->tx_wrq, lnet_cpt_table(), ps->ps_cpt, LIBCFS_CPT_ALLOC(tx->tx_wrq, lnet_cpt_table(), ps->ps_cpt,
(1 + IBLND_MAX_RDMA_FRAGS) * (1 + IBLND_MAX_RDMA_FRAGS) *
......
...@@ -689,6 +689,10 @@ kiblnd_setup_rd_iov(lnet_ni_t *ni, kib_tx_t *tx, kib_rdma_desc_t *rd, ...@@ -689,6 +689,10 @@ kiblnd_setup_rd_iov(lnet_ni_t *ni, kib_tx_t *tx, kib_rdma_desc_t *rd,
sg_set_page(sg, page, fragnob, page_offset); sg_set_page(sg, page, fragnob, page_offset);
sg = sg_next(sg); sg = sg_next(sg);
if (!sg) {
CERROR("lacking enough sg entries to map tx\n");
return -EFAULT;
}
if (offset + fragnob < iov->iov_len) { if (offset + fragnob < iov->iov_len) {
offset += fragnob; offset += fragnob;
...@@ -733,6 +737,10 @@ kiblnd_setup_rd_kiov(lnet_ni_t *ni, kib_tx_t *tx, kib_rdma_desc_t *rd, ...@@ -733,6 +737,10 @@ kiblnd_setup_rd_kiov(lnet_ni_t *ni, kib_tx_t *tx, kib_rdma_desc_t *rd,
sg_set_page(sg, kiov->kiov_page, fragnob, sg_set_page(sg, kiov->kiov_page, fragnob,
kiov->kiov_offset + offset); kiov->kiov_offset + offset);
sg = sg_next(sg); sg = sg_next(sg);
if (!sg) {
CERROR("lacking enough sg entries to map tx\n");
return -EFAULT;
}
offset = 0; offset = 0;
kiov++; kiov++;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment