lkml.org 
[lkml]   [2021]   [Nov]   [1]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH 5.10 43/77] nvme-tcp: fix possible req->offset corruption
    Date
    From: Varun Prakash <varun@chelsio.com>

    commit ce7723e9cdae4eb3030da082876580f4b2dc0861 upstream.

    With commit db5ad6b7f8cd ("nvme-tcp: try to send request in queue_rq
    context") r2t and response PDU can get processed while send function
    is executing.

    Current data digest send code uses req->offset after kernel_sendmsg(),
    this creates a race condition where req->offset gets reset before it
    is used in send function.

    This can happen in two cases -
    1. Target sends r2t PDU which resets req->offset.
    2. Target send response PDU which completes the req and then req is
    used for a new command, nvme_tcp_setup_cmd_pdu() resets req->offset.

    Fix this by storing req->offset in a local variable and using
    this local variable after kernel_sendmsg().

    Fixes: db5ad6b7f8cd ("nvme-tcp: try to send request in queue_rq context")
    Signed-off-by: Varun Prakash <varun@chelsio.com>
    Reviewed-by: Keith Busch <kbusch@kernel.org>
    Reviewed-by: Sagi Grimberg <sagi@grimberg.me>
    Signed-off-by: Christoph Hellwig <hch@lst.de>
    Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
    ---
    drivers/nvme/host/tcp.c | 3 ++-
    1 file changed, 2 insertions(+), 1 deletion(-)

    --- a/drivers/nvme/host/tcp.c
    +++ b/drivers/nvme/host/tcp.c
    @@ -1037,6 +1037,7 @@ static int nvme_tcp_try_send_data_pdu(st
    static int nvme_tcp_try_send_ddgst(struct nvme_tcp_request *req)
    {
    struct nvme_tcp_queue *queue = req->queue;
    + size_t offset = req->offset;
    int ret;
    struct msghdr msg = { .msg_flags = MSG_DONTWAIT };
    struct kvec iov = {
    @@ -1053,7 +1054,7 @@ static int nvme_tcp_try_send_ddgst(struc
    if (unlikely(ret <= 0))
    return ret;

    - if (req->offset + ret == NVME_TCP_DIGEST_LENGTH) {
    + if (offset + ret == NVME_TCP_DIGEST_LENGTH) {
    nvme_tcp_done_send_req(queue);
    return 1;
    }

    \
     
     \ /
      Last update: 2021-11-01 10:36    [W:4.040 / U:0.064 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site