Commit 188f7e8a authored by James Smart's avatar James Smart Committed by Jens Axboe

nvmet_fc: fix crashes on bad opcodes

if a nvme command is issued with an opcode that is not supported by
the target (example: opcode 21 - detach namespace), the target
crashes due to a null pointer.

nvmet_req_init() detects the bad opcode and immediately calls the nvme
command done routine with an error status, allowing the transport to
send the response. However, the FC transport was aborting the command
on error, so the abort freed the lldd point, but the rsp transmit path
referenced it psot the free.

Fix by removing the abort call on nvmet_req_init() failure.
The completion response will be sent with an error status code.

As the completion path will terminate the io, ensure the data_sg
lists show an unused state so that teardown paths are successful.
Signed-off-by: default avatarPaul Ely <Paul.Ely@broadcom.com>
Signed-off-by: default avatarJames Smart <james.smart@broadcom.com>
Reviewed-by: default avatarChristoph Hellwig <hch@lst.de>
Signed-off-by: default avatarSagi Grimberg <sagi@grimberg.me>
Signed-off-by: default avatarJens Axboe <axboe@kernel.dk>
parent 0b5a7669
...@@ -2096,20 +2096,22 @@ nvmet_fc_handle_fcp_rqst(struct nvmet_fc_tgtport *tgtport, ...@@ -2096,20 +2096,22 @@ nvmet_fc_handle_fcp_rqst(struct nvmet_fc_tgtport *tgtport,
/* clear any response payload */ /* clear any response payload */
memset(&fod->rspiubuf, 0, sizeof(fod->rspiubuf)); memset(&fod->rspiubuf, 0, sizeof(fod->rspiubuf));
fod->data_sg = NULL;
fod->data_sg_cnt = 0;
ret = nvmet_req_init(&fod->req, ret = nvmet_req_init(&fod->req,
&fod->queue->nvme_cq, &fod->queue->nvme_cq,
&fod->queue->nvme_sq, &fod->queue->nvme_sq,
&nvmet_fc_tgt_fcp_ops); &nvmet_fc_tgt_fcp_ops);
if (!ret) { /* bad SQE content or invalid ctrl state */ if (!ret) {
nvmet_fc_abort_op(tgtport, fod); /* bad SQE content or invalid ctrl state */
/* nvmet layer has already called op done to send rsp. */
return; return;
} }
/* keep a running counter of tail position */ /* keep a running counter of tail position */
atomic_inc(&fod->queue->sqtail); atomic_inc(&fod->queue->sqtail);
fod->data_sg = NULL;
fod->data_sg_cnt = 0;
if (fod->total_length) { if (fod->total_length) {
ret = nvmet_fc_alloc_tgt_pgs(fod); ret = nvmet_fc_alloc_tgt_pgs(fod);
if (ret) { if (ret) {
......
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