[PATCH 1/4] nvme-tcp: fix a possible use-after-free in controller reset during load

Sagi Grimberg sagi at grimberg.me
Sun Jan 30 01:21:16 PST 2022


Unlike .queue_rq, .submit_async_event does not check the ctrl and
queue readiness for submitting a AER. This may lead to a use-after-free
condition in the following scenario:
1. nvme_tcp_reset_ctrl_work
2. -> nvme_stop_ctrl flushes ctrl async_event_work
3. ctrl sends AEN which is received by the host, which in turn
   schedules AEN handling
4. teardown admin queue (which releases the queue socket)
5. AEN processed, submits another AER, calling nvme-tcp driver to submit
   prepares the cmd and schedules io_work
6. io_work triggers and attempts to send the cmd
==> use-after-free

In order to fix that, add ctrl and queue state check to validate the driver
is actually able to accept the socket send.

This solves the above race in the reset flow because the ctrl state is
changed to RESETTING, then the async_event_work is flushed, hence from
that point, any other AER command will find the ctrl state to be RESETTING
and bail out without scheduling io_work.

CC: stable at vger.kernel.org
Tested-by: Chris Leech <cleech at redhat.com>
Signed-off-by: Sagi Grimberg <sagi at grimberg.me>
---
 drivers/nvme/host/tcp.c | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/drivers/nvme/host/tcp.c b/drivers/nvme/host/tcp.c
index 4ceb28675fdf..447bae34f2cb 100644
--- a/drivers/nvme/host/tcp.c
+++ b/drivers/nvme/host/tcp.c
@@ -2211,6 +2211,10 @@ static void nvme_tcp_submit_async_event(struct nvme_ctrl *arg)
 	struct nvme_tcp_cmd_pdu *pdu = ctrl->async_req.pdu;
 	struct nvme_command *cmd = &pdu->cmd;
 	u8 hdgst = nvme_tcp_hdgst_len(queue);
+	bool queue_ready = test_bit(NVME_TCP_Q_LIVE, &queue->flags);
+
+	if (ctrl->ctrl.state != NVME_CTRL_LIVE || !queue_ready)
+		return;
 
 	memset(pdu, 0, sizeof(*pdu));
 	pdu->hdr.type = nvme_tcp_cmd;
-- 
2.30.2




More information about the Linux-nvme mailing list