Skip to content

Commit bf93585

Browse files
committed
Merge branch 'nvme-4.19' of git://git.infradead.org/nvme into for-linus
Pull single NVMe fix from Christoph. * 'nvme-4.19' of git://git.infradead.org/nvme: nvmet-rdma: fix possible bogus dereference under heavy load
2 parents d5274b3 + 8407879 commit bf93585

File tree

1 file changed

+25
-2
lines changed

1 file changed

+25
-2
lines changed

drivers/nvme/target/rdma.c

Lines changed: 25 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,7 @@ struct nvmet_rdma_rsp {
6666

6767
struct nvmet_req req;
6868

69+
bool allocated;
6970
u8 n_rdma;
7071
u32 flags;
7172
u32 invalidate_rkey;
@@ -174,11 +175,19 @@ nvmet_rdma_get_rsp(struct nvmet_rdma_queue *queue)
174175
unsigned long flags;
175176

176177
spin_lock_irqsave(&queue->rsps_lock, flags);
177-
rsp = list_first_entry(&queue->free_rsps,
178+
rsp = list_first_entry_or_null(&queue->free_rsps,
178179
struct nvmet_rdma_rsp, free_list);
179-
list_del(&rsp->free_list);
180+
if (likely(rsp))
181+
list_del(&rsp->free_list);
180182
spin_unlock_irqrestore(&queue->rsps_lock, flags);
181183

184+
if (unlikely(!rsp)) {
185+
rsp = kmalloc(sizeof(*rsp), GFP_KERNEL);
186+
if (unlikely(!rsp))
187+
return NULL;
188+
rsp->allocated = true;
189+
}
190+
182191
return rsp;
183192
}
184193

@@ -187,6 +196,11 @@ nvmet_rdma_put_rsp(struct nvmet_rdma_rsp *rsp)
187196
{
188197
unsigned long flags;
189198

199+
if (rsp->allocated) {
200+
kfree(rsp);
201+
return;
202+
}
203+
190204
spin_lock_irqsave(&rsp->queue->rsps_lock, flags);
191205
list_add_tail(&rsp->free_list, &rsp->queue->free_rsps);
192206
spin_unlock_irqrestore(&rsp->queue->rsps_lock, flags);
@@ -776,6 +790,15 @@ static void nvmet_rdma_recv_done(struct ib_cq *cq, struct ib_wc *wc)
776790

777791
cmd->queue = queue;
778792
rsp = nvmet_rdma_get_rsp(queue);
793+
if (unlikely(!rsp)) {
794+
/*
795+
* we get here only under memory pressure,
796+
* silently drop and have the host retry
797+
* as we can't even fail it.
798+
*/
799+
nvmet_rdma_post_recv(queue->dev, cmd);
800+
return;
801+
}
779802
rsp->queue = queue;
780803
rsp->cmd = cmd;
781804
rsp->flags = 0;

0 commit comments

Comments
 (0)