[PATCH] nvmet-tcp: bound sgl->length check in nvmet_tcp_map_data()
Maurizio Lombardi
mlombard at arkamax.eu
Thu Mar 19 00:59:06 PDT 2026
On Thu Mar 19, 2026 at 2:26 AM CET, Shivam Kumar wrote:
> nvmet_tcp_map_data() reads the SGL length from the incoming NVMe command
> and passes it to sgl_alloc() for scatter-gather allocation. The only
> existing size check (len > inline_data_size) is gated behind
> sgl->type == NVME_SGL_FMT_DATA_DESC | NVME_SGL_FMT_OFFSET, meaning any
> other SGL type bypasses the validation entirely. A remote attacker can
> send a CapsuleCmd with a non-offset SGL type and a large sgl->length
> (e.g. ~3 GB) to trigger an excessive kernel allocation, resulting in a
> page allocator WARNING and kernel panic when panic_on_warn is set.
>
> Add an upper-bound check against NVMET_TCP_MAXH2CDATA before calling
> sgl_alloc(). This value is already advertised to the host in the ICResp
> maxdata field as the maximum data transfer size.
>
> Signed-off-by: Shivam Kumar <kumar.shivam43666 at gmail.com>
> ---
> drivers/nvme/target/tcp.c | 2 ++
> 1 file changed, 2 insertions(+)
>
> diff --git a/drivers/nvme/target/tcp.c b/drivers/nvme/target/tcp.c
> index a456dd2fd8bd..c7253221c342 100644
> --- a/drivers/nvme/target/tcp.c
> +++ b/drivers/nvme/target/tcp.c
> @@ -431,6 +431,8 @@ static int nvmet_tcp_map_data(struct nvmet_tcp_cmd *cmd)
> return NVME_SC_SGL_INVALID_OFFSET | NVME_STATUS_DNR;
> cmd->pdu_len = len;
> }
> + if (len > NVMET_TCP_MAXH2CDATA)
> + return NVME_SC_SGL_INVALID_DATA | NVME_STATUS_DNR;
> cmd->req.transfer_len += len;
>
> cmd->req.sg = sgl_alloc(len, GFP_KERNEL, &cmd->req.sg_cnt);
I am not sure this patch is correct, the intent is valid but you are conflating
the total transfer size with the H2CData maximum PDU size.
In other words, if I understood the code correctly:
MAXH2CDATA is the limit of a single H2CData packet's size.
sgl->length is the total amount of data to transfer.
Also, will the request be completed with "NVME_SC_SGL_INVALID_DATA |
NVME_STATUS_DNR" code? If yes, this would be a violation of the spec
that states that an H2CDATA with a too large size should trigger a
fatal transport error.
Maybe the correct fix is to set a sane default for MDTS
(Maximum Data Transfer Size), at the moment it's left to zero (no limit).
Maurizio
More information about the Linux-nvme
mailing list