From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from mail-pl1-f174.google.com (mail-pl1-f174.google.com [209.85.214.174]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 632DC3612CF for ; Wed, 29 Jul 2026 05:46:26 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.214.174 ARC-Seal:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1785303991; cv=none; b=O48j4+k/NrwcIS7IG/I1oBx3tYX+exbHSQc4+xHhdsJPW4TUKuzKTfufCX4gr6CZvEGv+DTFoS1BmAEZuGHajNKF/J0MNgXChUj8w7qDDp3oK2l7JBBK0w4kIWm8o0FGeLan8qG1qfbVfqqQ4MG7sWMsDBu3H0N6EeyWPcjUzx8= ARC-Message-Signature:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1785303991; c=relaxed/simple; bh=HVaiWdHWc+xF74J816n1HAl1ifPsYvkHezSJeMUW+kM=; h=From:To:Cc:Subject:Date:Message-ID:MIME-Version; b=jG5m+vaI5l0PdxNsCQA7FQSnR+gaFR4/uvxqpEBebjp1S4DMPz5BrYjJVlBBvz6QVZ7VTr1vMVUOmpIajZdYQXg/bNkeqtnSGLGKzq5Gp7ChWUZl+4bj+EsGsLGrJm2Wy0WlmBsEr1vLr4GmVf7yARu3PxzBuwBQp11RHvFl19M= ARC-Authentication-Results:i=1; smtp.subspace.kernel.org; dmarc=fail (p=none dis=none) header.from=isslab.korea.ac.kr; spf=none smtp.mailfrom=isslab.korea.ac.kr; dkim=pass (2048-bit key) header.d=isslab-korea-ac-kr.20251104.gappssmtp.com header.i=@isslab-korea-ac-kr.20251104.gappssmtp.com header.b=j3dz7Bch; arc=none smtp.client-ip=209.85.214.174 Authentication-Results: smtp.subspace.kernel.org; dmarc=fail (p=none dis=none) header.from=isslab.korea.ac.kr Authentication-Results: smtp.subspace.kernel.org; spf=none smtp.mailfrom=isslab.korea.ac.kr Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=isslab-korea-ac-kr.20251104.gappssmtp.com header.i=@isslab-korea-ac-kr.20251104.gappssmtp.com header.b="j3dz7Bch" Received: by mail-pl1-f174.google.com with SMTP id d9443c01a7336-2caea3f742bso8030945ad.0 for ; Tue, 28 Jul 2026 22:46:26 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=isslab-korea-ac-kr.20251104.gappssmtp.com; s=20251104; t=1785303986; x=1785908786; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:message-id:date:subject:cc :to:from:from:to:cc:subject:date:message-id:reply-to:content-type; bh=N2OUE4XFPbIApySv4cd9+4/cmn0pHnKsOVRWx7UtEcY=; b=j3dz7BchzMx3jECSTV6wrozRajDg8riyxup2iag1/PwXb00ID434B/0LYd4DzEzbZ1 6wUmHLjKwDS5xn0Qi/TeZnAsm9o/sf6uQVMdb2Q79e8ZzKq9ACZvWIZTW0mfd2gZgd47 ujamIDab0sL+2oLM9BR7jn+kYbjjvVvFXLn5Q/tG2gi6Jwkc9jKKuvUxItxEzys74h1J Vc9PBZgUCbssp8YznK1qfSDSbJyG++N0OOTZgEvR2LvU25pUBqR5Lz+LHtQpscTElcfN DaI3bD0PSrpBhNh0p6zBbfI+6zz1IFNe6qAoEIeFhBtcjhtk4dZxZPH6I105oUc45JqB /v/w== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1785303986; x=1785908786; h=content-transfer-encoding:mime-version:message-id:date:subject:cc :to:from:x-gm-gg:x-gm-message-state:from:to:cc:subject:date :message-id:reply-to:content-type; bh=N2OUE4XFPbIApySv4cd9+4/cmn0pHnKsOVRWx7UtEcY=; b=JnHAQdi3+qHCFJ/f/VC9Ezu43NmkMrklwopJ3Gniy0GL74sbNoXx5dvEPGaHbfkAW3 KWUfJN1N+9HKj4xDm8etH7KUm9GqgRMH076frrtwDpmYj5NKOJNMWHMvuUt751sr3Kth lsWuTYOrBekxp1HvHblg/rTM7Lr3oPVhv9Wvb5X3guIC9tL9DEGwSiB8f2r2hHVD33kw mBKAx5t6zkcxGtbi+B4vwPA2RWvCChk7+UqcRw0eGj9SxYNCVQzdZ/G9xOGvpp7MgQrH bECqROf05eQQffGcJtrTolx3/W1OzVLcSwm3gUyHj7NG6eyawc7nbF7w8d1nU3RaAnZq BH9Q== X-Forwarded-Encrypted: i=1; AHgh+RpEX5Y2971sDLgmixNkMEe/sLgs7hH4lIYf05Qjok0+CPz8Oc0/O0c+SXF/6B8EF9cUr1M/JLSJUu5skaI=@vger.kernel.org X-Gm-Message-State: AOJu0YxEw0ZUi0Ku1RhKiyNzhi0WjAqxbTSJGHEawtdBW0O5qbNloImt MkY6r9xxmGhWkHfa0gCBrVBuxQXl1wv6SAl4ltIxoLuERWEeMQwtdwZUEZvmx/Ub228= X-Gm-Gg: AR+sD12XIWBawpI8hkWJ0RYZZBNypyQ1sDyn8SuGt6go+bNSavb4gDCtOoUuX+9HuxP m3N1K5nY8eY7yWa9VvUHG/Z3L9+FK8t07zpdfyR2KuEQpPH9KEEYm6P1u41us95qILi2k27IYnQ YoFng5IGYN293mTWJmOpUdL2zFjhaWPAE6/c0utGZpHwJiQyX4hNXz7OBvYL+G6U08uWowDobQF 8+tCIBG9g9+Y301PYB2eF34u/s5z3bF4atkxszucGEwrN4kT5xcOh3hPYl+J0EXQqMZFOB8/6BS /YsJpj29Vjd7clXHtZy4yhNZHIV5nirEVv4Hi1fLxsBgWFfyBRQmQIfC9Y4a5fojTwAagdlrMNK M72I5ZHznpAcojio8bRO8XZVHi1QOdRKt7vJ7lv0dESWyiwTRhcicgqDCO4g40g9hiRNYOKAMew EN2m3I0NHX7ZgttBxB5hOtlou59lp7VvVkcNfKbsIwqFkV67m1BpFtrgXBpsA9PUmkGqKpB0LFT PBWS9g= X-Received: by 2002:a17:903:2d0:b0:2ca:bb7e:29a7 with SMTP id d9443c01a7336-2d015ec9f0amr61452225ad.41.1785303986436; Tue, 28 Jul 2026 22:46:26 -0700 (PDT) Received: from yhlee-960QFG.. ([125.131.91.97]) by smtp.gmail.com with ESMTPSA id d9443c01a7336-2d022a45979sm5817845ad.18.2026.07.28.22.46.23 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 28 Jul 2026 22:46:25 -0700 (PDT) From: Yehyeong Lee To: linux-nvme@lists.infradead.org Cc: kbusch@kernel.org, axboe@kernel.dk, hch@lst.de, sagi@grimberg.me, linux-kernel@vger.kernel.org, Yehyeong Lee , stable@vger.kernel.org, Solganik Alexander , Roy Shterman Subject: [PATCH] nvme-tcp: fix host memory disclosure on R2T for a read command Date: Wed, 29 Jul 2026 14:46:02 +0900 Message-ID: <20260729054602.1237120-1-yhlee@isslab.korea.ac.kr> X-Mailer: git-send-email 2.43.0 Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: 8bit nvme_tcp_handle_r2t() does not check the direction of the request the R2T refers to. A malicious controller can send an R2T for a READ and the host will answer it: nvme_tcp_setup_h2c_data_pdu() builds the H2CData header and nvme_tcp_try_send_data() sends the request's data buffer. That buffer is the READ destination, so its contents go to the controller. The command then completes normally and nothing is logged. Against a test controller that answers every READ with an R2T, a 4096 byte buffered read returned all 4096 bytes, split over two R2Ts. The pages contained stale kernel data, including an array of struct page pointers. Reject an R2T for a request that is not a write. Fixes: 3f2304f8c6d6 ("nvme-tcp: add NVMe over TCP host driver") Cc: stable@vger.kernel.org Signed-off-by: Yehyeong Lee --- c2hdata has the same gap - nvme_tcp_handle_c2h_data() doesn't check direction either - but a write's iterator is ITER_SOURCE, so _copy_to_iter() refuses the copy. It does that with WARN_ON_ONCE(), which a controller can then trigger remotely. That seems like a separate problem; I haven't looked at it properly yet. Tested on v7.2-rc5 with a controller that answers every READ with an R2T. 68 of 68 H2CData PDUs came back with the read buffer before the patch, none after. Writes larger than the inline capsule size still go through the normal R2T path. drivers/nvme/host/tcp.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/drivers/nvme/host/tcp.c b/drivers/nvme/host/tcp.c index ba5c7b3e2a7c..07cda97ffab6 100644 --- a/drivers/nvme/host/tcp.c +++ b/drivers/nvme/host/tcp.c @@ -745,6 +745,13 @@ static int nvme_tcp_handle_r2t(struct nvme_tcp_queue *queue, } req = blk_mq_rq_to_pdu(rq); + if (unlikely(rq_data_dir(rq) != WRITE)) { + dev_err(queue->ctrl->ctrl.device, + "req %d unexpected r2t for a non-write command\n", + rq->tag); + return -EPROTO; + } + if (unlikely(!r2t_length)) { dev_err(queue->ctrl->ctrl.device, "req %d r2t len is %u, probably a bug...\n", -- 2.43.0