public inbox for linux-nvme@lists.infradead.org
 help / color / mirror / Atom feed
* [PATCH 0/2] Fix some kernel panics due to the host sending invalid PDUs
@ 2023-12-21 16:31 Maurizio Lombardi
  2023-12-21 16:31 ` [PATCH 1/2] nvmet-tcp: Fix a kernel panic when host sends an invalid H2C PDU length Maurizio Lombardi
  2023-12-21 16:31 ` [PATCH 2/2] nvmet-tcp: fix a crash in nvmet_req_complete() Maurizio Lombardi
  0 siblings, 2 replies; 6+ messages in thread
From: Maurizio Lombardi @ 2023-12-21 16:31 UTC (permalink / raw)
  To: sagi; +Cc: zahavi.alon, hch, chaitanyak, linux-nvme, kbusch

I used the reproducer that was published here:
https://lore.kernel.org/linux-nvme/89a927a6-2baf-434a-b1d5-50fb99beca73@grimberg.me/T/#m57f25abc944dc706125fed02cb99d86b56c5d36e

I didn't get the same call trace, however.

Maurizio Lombardi (2):
  nvmet-tcp: Fix a kernel panic when host sends an invalid H2C PDU
    length
  nvmet-tcp: fix a crash in nvmet_req_complete()

 drivers/nvme/target/tcp.c | 13 ++++++++++---
 1 file changed, 10 insertions(+), 3 deletions(-)

-- 
2.39.3



^ permalink raw reply	[flat|nested] 6+ messages in thread

* [PATCH 1/2] nvmet-tcp: Fix a kernel panic when host sends an invalid H2C PDU length
  2023-12-21 16:31 [PATCH 0/2] Fix some kernel panics due to the host sending invalid PDUs Maurizio Lombardi
@ 2023-12-21 16:31 ` Maurizio Lombardi
  2023-12-21 17:42   ` Keith Busch
  2023-12-21 16:31 ` [PATCH 2/2] nvmet-tcp: fix a crash in nvmet_req_complete() Maurizio Lombardi
  1 sibling, 1 reply; 6+ messages in thread
From: Maurizio Lombardi @ 2023-12-21 16:31 UTC (permalink / raw)
  To: sagi; +Cc: zahavi.alon, hch, chaitanyak, linux-nvme, kbusch

If the host sends an H2CData command with a DATAL field equal to 0,
the kernel crashes in nvmet_tcp_build_pdu_iovec().

Unable to handle kernel NULL pointer dereference at
virtual address 0000000000000000
lr : nvmet_tcp_io_work+0x6ac/0x718 [nvmet_tcp]
Call trace:
  process_one_work+0x174/0x3c8
  worker_thread+0x2d0/0x3e8
  kthread+0x104/0x110

Getting an H2CData Packet with DATAL=0 is unexpected, treat it
like a fatal transport error.
Also, the PDU length should never exceed the MAXH2CDATA parameter which
has been communicated to the host in nvmet_tcp_handle_icreq().

Signed-off-by: Maurizio Lombardi <mlombard@redhat.com>
---
 drivers/nvme/target/tcp.c | 10 +++++++++-
 1 file changed, 9 insertions(+), 1 deletion(-)

diff --git a/drivers/nvme/target/tcp.c b/drivers/nvme/target/tcp.c
index 4cc27856aa8f..44eda6081e99 100644
--- a/drivers/nvme/target/tcp.c
+++ b/drivers/nvme/target/tcp.c
@@ -24,6 +24,7 @@
 #include "nvmet.h"
 
 #define NVMET_TCP_DEF_INLINE_DATA_SIZE	(4 * PAGE_SIZE)
+#define NVMET_TCP_MAXH2CDATA		0x400000 /* 16M arbitrary limit */
 
 static int param_store_val(const char *str, int *val, int min, int max)
 {
@@ -923,7 +924,7 @@ static int nvmet_tcp_handle_icreq(struct nvmet_tcp_queue *queue)
 	icresp->hdr.pdo = 0;
 	icresp->hdr.plen = cpu_to_le32(icresp->hdr.hlen);
 	icresp->pfv = cpu_to_le16(NVME_TCP_PFV_1_0);
-	icresp->maxdata = cpu_to_le32(0x400000); /* 16M arbitrary limit */
+	icresp->maxdata = cpu_to_le32(NVMET_TCP_MAXH2CDATA);
 	icresp->cpda = 0;
 	if (queue->hdr_digest)
 		icresp->digest |= NVME_TCP_HDR_DIGEST_ENABLE;
@@ -1002,6 +1003,13 @@ static int nvmet_tcp_handle_h2c_data_pdu(struct nvmet_tcp_queue *queue)
 	}
 
 	cmd->pdu_len = le32_to_cpu(data->data_length);
+	if (unlikely(cmd->pdu_len == 0 ||
+		     cmd->pdu_len > NVMET_TCP_MAXH2CDATA)) {
+		pr_err("H2CData PDU len out of range\n");
+		/* FIXME: use proper transport errors */
+		nvmet_tcp_fatal_error(queue);
+		return -EPROTO;
+	}
 	cmd->pdu_recv = 0;
 	nvmet_tcp_build_pdu_iovec(cmd);
 	queue->cmd = cmd;
-- 
2.39.3



^ permalink raw reply related	[flat|nested] 6+ messages in thread

* [PATCH 2/2] nvmet-tcp: fix a crash in nvmet_req_complete()
  2023-12-21 16:31 [PATCH 0/2] Fix some kernel panics due to the host sending invalid PDUs Maurizio Lombardi
  2023-12-21 16:31 ` [PATCH 1/2] nvmet-tcp: Fix a kernel panic when host sends an invalid H2C PDU length Maurizio Lombardi
@ 2023-12-21 16:31 ` Maurizio Lombardi
  2023-12-21 21:19   ` Keith Busch
  1 sibling, 1 reply; 6+ messages in thread
From: Maurizio Lombardi @ 2023-12-21 16:31 UTC (permalink / raw)
  To: sagi; +Cc: zahavi.alon, hch, chaitanyak, linux-nvme, kbusch

in nvmet_tcp_handle_h2c_data_pdu(), if the host sends a data_offset
different from rbytes_done, the driver ends up calling nvmet_req_complete()
passing a status error.
The problem is that at this point cmd->req is not yet initialized,
the kernel will crash after dereferencing a NULL pointer.

Fix the bug by replacing the call to nvmet_req_complete() with
nvmet_tcp_fatal_error().

Signed-off-by: Maurizio Lombardi <mlombard@redhat.com>
---
 drivers/nvme/target/tcp.c | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/drivers/nvme/target/tcp.c b/drivers/nvme/target/tcp.c
index 44eda6081e99..0e719460199f 100644
--- a/drivers/nvme/target/tcp.c
+++ b/drivers/nvme/target/tcp.c
@@ -997,8 +997,7 @@ static int nvmet_tcp_handle_h2c_data_pdu(struct nvmet_tcp_queue *queue)
 			data->ttag, le32_to_cpu(data->data_offset),
 			cmd->rbytes_done);
 		/* FIXME: use path and transport errors */
-		nvmet_req_complete(&cmd->req,
-			NVME_SC_INVALID_FIELD | NVME_SC_DNR);
+		nvmet_tcp_fatal_error(queue);
 		return -EPROTO;
 	}
 
-- 
2.39.3



^ permalink raw reply related	[flat|nested] 6+ messages in thread

* Re: [PATCH 1/2] nvmet-tcp: Fix a kernel panic when host sends an invalid H2C PDU length
  2023-12-21 16:31 ` [PATCH 1/2] nvmet-tcp: Fix a kernel panic when host sends an invalid H2C PDU length Maurizio Lombardi
@ 2023-12-21 17:42   ` Keith Busch
  2023-12-22  8:41     ` Maurizio Lombardi
  0 siblings, 1 reply; 6+ messages in thread
From: Keith Busch @ 2023-12-21 17:42 UTC (permalink / raw)
  To: Maurizio Lombardi; +Cc: sagi, zahavi.alon, hch, chaitanyak, linux-nvme

On Thu, Dec 21, 2023 at 05:31:53PM +0100, Maurizio Lombardi wrote:
> @@ -1002,6 +1003,13 @@ static int nvmet_tcp_handle_h2c_data_pdu(struct nvmet_tcp_queue *queue)
>  	}
>  
>  	cmd->pdu_len = le32_to_cpu(data->data_length);
> +	if (unlikely(cmd->pdu_len == 0 ||
> +		     cmd->pdu_len > NVMET_TCP_MAXH2CDATA)) {
> +		pr_err("H2CData PDU len out of range\n");

Please add the 'pdu_len' to the pr_err since that info sounds useful to
knowing which type of target error we're dealing with.

Otherwise looks good!

Reviewed-by: Keith Busch <kbusch@kernel.org>

> +		/* FIXME: use proper transport errors */
> +		nvmet_tcp_fatal_error(queue);
> +		return -EPROTO;
> +	}
>  	cmd->pdu_recv = 0;
>  	nvmet_tcp_build_pdu_iovec(cmd);
>  	queue->cmd = cmd;


^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [PATCH 2/2] nvmet-tcp: fix a crash in nvmet_req_complete()
  2023-12-21 16:31 ` [PATCH 2/2] nvmet-tcp: fix a crash in nvmet_req_complete() Maurizio Lombardi
@ 2023-12-21 21:19   ` Keith Busch
  0 siblings, 0 replies; 6+ messages in thread
From: Keith Busch @ 2023-12-21 21:19 UTC (permalink / raw)
  To: Maurizio Lombardi; +Cc: sagi, zahavi.alon, hch, chaitanyak, linux-nvme

On Thu, Dec 21, 2023 at 05:31:54PM +0100, Maurizio Lombardi wrote:
> in nvmet_tcp_handle_h2c_data_pdu(), if the host sends a data_offset
> different from rbytes_done, the driver ends up calling nvmet_req_complete()
> passing a status error.
> The problem is that at this point cmd->req is not yet initialized,
> the kernel will crash after dereferencing a NULL pointer.
> 
> Fix the bug by replacing the call to nvmet_req_complete() with
> nvmet_tcp_fatal_error().

Looks good. The bug this fixes goes back to the beginning:

Fixes: 872d26a391da92 ("nvmet-tcp: add NVMe over TCP target driver")

Reviewed-by: Keith Busch <kbsuch@kernel.org>


^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [PATCH 1/2] nvmet-tcp: Fix a kernel panic when host sends an invalid H2C PDU length
  2023-12-21 17:42   ` Keith Busch
@ 2023-12-22  8:41     ` Maurizio Lombardi
  0 siblings, 0 replies; 6+ messages in thread
From: Maurizio Lombardi @ 2023-12-22  8:41 UTC (permalink / raw)
  To: Keith Busch; +Cc: sagi, zahavi.alon, hch, chaitanyak, linux-nvme

čt 21. 12. 2023 v 18:42 odesílatel Keith Busch <kbusch@kernel.org> napsal:
>
> On Thu, Dec 21, 2023 at 05:31:53PM +0100, Maurizio Lombardi wrote:
> Please add the 'pdu_len' to the pr_err since that info sounds useful to
> knowing which type of target error we're dealing with.
>
> Otherwise looks good!
>
> Reviewed-by: Keith Busch <kbusch@kernel.org>
>

Thanks,

I realized that there is still a possible problem, the data_length
sent by the host
could be inside the allowed range, but still higher than the real size
of the packet.
This could make the kernel crash.

Today I will send a V2 and add more fixes to this patchset.

Maurizio



^ permalink raw reply	[flat|nested] 6+ messages in thread

end of thread, other threads:[~2023-12-22  8:41 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2023-12-21 16:31 [PATCH 0/2] Fix some kernel panics due to the host sending invalid PDUs Maurizio Lombardi
2023-12-21 16:31 ` [PATCH 1/2] nvmet-tcp: Fix a kernel panic when host sends an invalid H2C PDU length Maurizio Lombardi
2023-12-21 17:42   ` Keith Busch
2023-12-22  8:41     ` Maurizio Lombardi
2023-12-21 16:31 ` [PATCH 2/2] nvmet-tcp: fix a crash in nvmet_req_complete() Maurizio Lombardi
2023-12-21 21:19   ` Keith Busch

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox