IB/srp: Add memory descriptor array pointer range checking
authorBart Van Assche <bart.vanassche@sandisk.com>
Tue, 11 Aug 2015 00:07:27 +0000 (17:07 -0700)
committerDoug Ledford <dledford@redhat.com>
Sun, 30 Aug 2015 22:12:37 +0000 (18:12 -0400)
Although most paths through which a request is submitted check
block layer parameters like the max_segments limit, these are
not checked when an SG_IO or direct I/O request is submitted.
Hence add a range check for the memory descriptor array pointer.

Signed-off-by: Bart Van Assche <bart.vanassche@sandisk.com>
Signed-off-by: Doug Ledford <dledford@redhat.com>
drivers/infiniband/ulp/srp/ib_srp.c
drivers/infiniband/ulp/srp/ib_srp.h

index 03ae72e338c0da2fc2b1294dcb44316af8d77e06..b7feb7424097d45d062dff4bb9b1ce80d8284ad8 100644 (file)
@@ -1277,12 +1277,15 @@ static int srp_map_finish_fmr(struct srp_map_state *state,
        struct ib_pool_fmr *fmr;
        u64 io_addr = 0;
 
+       if (state->fmr.next >= state->fmr.end)
+               return -ENOMEM;
+
        fmr = ib_fmr_pool_map_phys(ch->fmr_pool, state->pages,
                                   state->npages, io_addr);
        if (IS_ERR(fmr))
                return PTR_ERR(fmr);
 
-       *state->next_fmr++ = fmr;
+       *state->fmr.next++ = fmr;
        state->nmdesc++;
 
        srp_map_desc(state, state->base_dma_addr & ~dev->mr_page_mask,
@@ -1301,6 +1304,9 @@ static int srp_map_finish_fr(struct srp_map_state *state,
        struct srp_fr_desc *desc;
        u32 rkey;
 
+       if (state->fr.next >= state->fr.end)
+               return -ENOMEM;
+
        desc = srp_fr_pool_get(ch->fr_pool);
        if (!desc)
                return -ENOMEM;
@@ -1324,7 +1330,7 @@ static int srp_map_finish_fr(struct srp_map_state *state,
                                       IB_ACCESS_REMOTE_WRITE);
        wr.wr.fast_reg.rkey = desc->mr->lkey;
 
-       *state->next_fr++ = desc;
+       *state->fr.next++ = desc;
        state->nmdesc++;
 
        srp_map_desc(state, state->base_dma_addr, state->dma_len,
@@ -1450,10 +1456,12 @@ static int srp_map_sg(struct srp_map_state *state, struct srp_rdma_ch *ch,
        state->desc     = req->indirect_desc;
        state->pages    = req->map_page;
        if (dev->use_fast_reg) {
-               state->next_fr = req->fr_list;
+               state->fr.next = req->fr_list;
+               state->fr.end = req->fr_list + target->cmd_sg_cnt;
                use_mr = !!ch->fr_pool;
        } else {
-               state->next_fmr = req->fmr_list;
+               state->fmr.next = req->fmr_list;
+               state->fmr.end = req->fmr_list + target->cmd_sg_cnt;
                use_mr = !!ch->fmr_pool;
        }
 
index 17ee3f80ba550aec9c9ae9d326e2e91e2bb7daf0..2ab73bc76da176c50cff9c981effb3fe4d0778cb 100644 (file)
@@ -282,8 +282,14 @@ struct srp_fr_pool {
  */
 struct srp_map_state {
        union {
-               struct ib_pool_fmr **next_fmr;
-               struct srp_fr_desc **next_fr;
+               struct {
+                       struct ib_pool_fmr **next;
+                       struct ib_pool_fmr **end;
+               } fmr;
+               struct {
+                       struct srp_fr_desc **next;
+                       struct srp_fr_desc **end;
+               } fr;
        };
        struct srp_direct_buf  *desc;
        u64                    *pages;