Skip to content

Commit 25e5cb7

Browse files
sagigrimbergChristoph Hellwig
authored andcommitted
nvme-tcp: fix possible crash in write_zeroes processing
We cannot look at blk_rq_payload_bytes without first checking that the request has a mappable physical segments first (e.g. blk_rq_nr_phys_segments(rq) != 0) and only then to take the request payload bytes. This caused us to send a wrong sgl to the target or even dereference a non-existing buffer in case we actually got to the data send sequence (if it was in-capsule). Reported-by: Tony Asleson <[email protected]> Suggested-by: Chaitanya Kulkarni <[email protected]> Signed-off-by: Sagi Grimberg <[email protected]> Signed-off-by: Keith Busch <[email protected]> Signed-off-by: Christoph Hellwig <[email protected]>
1 parent d038dd8 commit 25e5cb7

File tree

1 file changed

+7
-6
lines changed

1 file changed

+7
-6
lines changed

drivers/nvme/host/tcp.c

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -174,16 +174,14 @@ static inline bool nvme_tcp_async_req(struct nvme_tcp_request *req)
174174
static inline bool nvme_tcp_has_inline_data(struct nvme_tcp_request *req)
175175
{
176176
struct request *rq;
177-
unsigned int bytes;
178177

179178
if (unlikely(nvme_tcp_async_req(req)))
180179
return false; /* async events don't have a request */
181180

182181
rq = blk_mq_rq_from_pdu(req);
183-
bytes = blk_rq_payload_bytes(rq);
184182

185-
return rq_data_dir(rq) == WRITE && bytes &&
186-
bytes <= nvme_tcp_inline_data_size(req->queue);
183+
return rq_data_dir(rq) == WRITE && req->data_len &&
184+
req->data_len <= nvme_tcp_inline_data_size(req->queue);
187185
}
188186

189187
static inline struct page *nvme_tcp_req_cur_page(struct nvme_tcp_request *req)
@@ -2164,7 +2162,9 @@ static blk_status_t nvme_tcp_map_data(struct nvme_tcp_queue *queue,
21642162

21652163
c->common.flags |= NVME_CMD_SGL_METABUF;
21662164

2167-
if (rq_data_dir(rq) == WRITE && req->data_len &&
2165+
if (!blk_rq_nr_phys_segments(rq))
2166+
nvme_tcp_set_sg_null(c);
2167+
else if (rq_data_dir(rq) == WRITE &&
21682168
req->data_len <= nvme_tcp_inline_data_size(queue))
21692169
nvme_tcp_set_sg_inline(queue, c, req->data_len);
21702170
else
@@ -2191,7 +2191,8 @@ static blk_status_t nvme_tcp_setup_cmd_pdu(struct nvme_ns *ns,
21912191
req->data_sent = 0;
21922192
req->pdu_len = 0;
21932193
req->pdu_sent = 0;
2194-
req->data_len = blk_rq_payload_bytes(rq);
2194+
req->data_len = blk_rq_nr_phys_segments(rq) ?
2195+
blk_rq_payload_bytes(rq) : 0;
21952196
req->curr_bio = rq->bio;
21962197

21972198
if (rq_data_dir(rq) == WRITE &&

0 commit comments

Comments
 (0)