nvmet-tcp: Fix the H2C expected PDU len calculation
authorMaurizio Lombardi <mlombard@redhat.com>
Fri, 5 Jan 2024 08:14:44 +0000 (09:14 +0100)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Thu, 25 Jan 2024 23:35:55 +0000 (15:35 -0800)
[ Upstream commit 9a1abc24850eb759e36a2f8869161c3b7254c904 ]

The nvmet_tcp_handle_h2c_data_pdu() function should take into
consideration the possibility that the header digest and/or the data
digests are enabled when calculating the expected PDU length, before
comparing it to the value stored in cmd->pdu_len.

Fixes: efa56305908b ("nvmet-tcp: Fix a kernel panic when host sends an invalid H2C PDU length")
Signed-off-by: Maurizio Lombardi <mlombard@redhat.com>
Reviewed-by: Sagi Grimberg <sagi@grimberg.me>
Signed-off-by: Keith Busch <kbusch@kernel.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
drivers/nvme/target/tcp.c

index 7f7fa78..a4f8027 100644 (file)
@@ -954,7 +954,7 @@ static int nvmet_tcp_handle_h2c_data_pdu(struct nvmet_tcp_queue *queue)
 {
        struct nvme_tcp_data_pdu *data = &queue->pdu.data;
        struct nvmet_tcp_cmd *cmd;
-       unsigned int plen;
+       unsigned int exp_data_len;
 
        if (likely(queue->nr_cmds)) {
                if (unlikely(data->ttag >= queue->nr_cmds)) {
@@ -977,9 +977,13 @@ static int nvmet_tcp_handle_h2c_data_pdu(struct nvmet_tcp_queue *queue)
                return -EPROTO;
        }
 
-       plen = le32_to_cpu(data->hdr.plen);
+       exp_data_len = le32_to_cpu(data->hdr.plen) -
+                       nvmet_tcp_hdgst_len(queue) -
+                       nvmet_tcp_ddgst_len(queue) -
+                       sizeof(*data);
+
        cmd->pdu_len = le32_to_cpu(data->data_length);
-       if (unlikely(cmd->pdu_len != (plen - sizeof(*data)) ||
+       if (unlikely(cmd->pdu_len != exp_data_len ||
                     cmd->pdu_len == 0 ||
                     cmd->pdu_len > NVMET_TCP_MAXH2CDATA)) {
                pr_err("H2CData PDU len %u is invalid\n", cmd->pdu_len);