mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
From: Yibo Liu <yiboliume@gmail.com>
To: "Philipp Reisner" <philipp.reisner@linbit.com>,
	"Lars Ellenberg" <lars.ellenberg@linbit.com>,
	"Christoph Böhmwalder" <christoph.boehmwalder@linbit.com>,
	"Jens Axboe" <axboe@kernel.dk>
Cc: drbd-dev@lists.linux.dev, linux-block@vger.kernel.org,
	linux-kernel@vger.kernel.org, Yibo Liu <yiboliume@gmail.com>
Subject: [PATCH 2/2] drbd: validate digest size in checksum resync and verify requests
Date: Thu, 15 Oct 2026 15:28:00 -0700	[thread overview]
Message-ID: <20261015222800.85928-3-yiboliume@gmail.com> (raw)
In-Reply-To: <20261015222800.85928-1-yiboliume@gmail.com>

receive_DataRequest() takes the digest length of P_CSUM_RS_REQUEST and
P_OV_REPLY packets from the packet header and passes it to kmalloc()
without any check. The worker later compares the received digest with
one computed by the local csums or verify algorithm. A size mismatch is
only reported by D_ASSERT(), and memcmp() runs anyway.

A digest that is shorter than the algorithm's digest size therefore
makes w_e_end_csum_rs_req() and w_e_end_ov_reply() read past the end of
the digest_info allocation:

  BUG: KASAN: slab-out-of-bounds in memcmp+0x1b8/0x1d8
  Read of size 8 at addr ffff00000a638610 by task drbd_w_r1/212
  Call trace:
   memcmp
   w_e_end_csum_rs_req
   drbd_worker
  Allocated by task 240:
   __kmalloc_noprof
   receive_DataRequest
   drbd_receiver

A digest length larger than the page allocator can serve triggers the
WARN_ON_ONCE() for oversized allocations, as GFP_NOIO does not include
__GFP_NOWARN:

  WARNING: mm/page_alloc.c:5340 at __alloc_frozen_pages_noprof
  Call trace:
   ___kmalloc_large_node
   __kmalloc_noprof
   receive_DataRequest
   drbd_receiver

Reject these packets unless the digest length matches the digest size
of the configured csums or verify algorithm, and also reject them when
no such algorithm is configured. In the worker, only compare digests of
the same size: the peer can switch csums-alg or verify-alg with
P_SYNC_PARAM after the request was received, and a size mismatch is
then treated as "not in sync" instead of reading out of bounds.

Fixes: b411b3637fa7 ("The DRBD driver")
Cc: stable@vger.kernel.org
Assisted-by: Claude:claude-opus-5-5
Signed-off-by: Yibo Liu <yiboliume@gmail.com>
---

Notes:
    - Reproduced in the same setup with csums-alg=sha1, the proxy rewriting
      one P_CSUM_RS_REQUEST: a 0-byte digest gives the KASAN report above,
      a 1 GiB digest length gives the WARNING above. With the patch both are
      rejected with "CsumRSRequest: unexpected digest size ..." and there is
      no KASAN report or warning. A complete csums-alg resync followed by an
      online verify with verify-alg=sha1, without tampering, still passes.
      The harness is available on request.
    - In LINBIT's DRBD 9 tree, receive_digest() only rejects negative sizes
      and the sender keeps the D_ASSERT() before memcmp(), so the pending
      DRBD 9 rework series probably needs the same checks. I have not
      checked the posted series itself.

 drivers/block/drbd/drbd_receiver.c | 9 +++++++++
 drivers/block/drbd/drbd_worker.c   | 8 ++++----
 2 files changed, 13 insertions(+), 4 deletions(-)

diff --git a/drivers/block/drbd/drbd_receiver.c b/drivers/block/drbd/drbd_receiver.c
index 97b306676626..87e714477050 100644
--- a/drivers/block/drbd/drbd_receiver.c
+++ b/drivers/block/drbd/drbd_receiver.c
@@ -2629,6 +2629,7 @@ static int receive_DataRequest(struct drbd_connection *connection, struct packet
 	sector_t capacity;
 	struct drbd_peer_request *peer_req;
 	struct digest_info *di = NULL;
+	struct crypto_shash *tfm;
 	int size, verb;
 	struct p_block_req *p =	pi->data;
 
@@ -2713,6 +2714,14 @@ static int receive_DataRequest(struct drbd_connection *connection, struct packet
 
 	case P_OV_REPLY:
 	case P_CSUM_RS_REQUEST:
+		tfm = pi->cmd == P_OV_REPLY ? connection->verify_tfm :
+					      connection->csums_tfm;
+		if (!tfm || pi->size != crypto_shash_digestsize(tfm)) {
+			drbd_err(device, "%s: unexpected digest size %u\n",
+				 cmdname(pi->cmd), pi->size);
+			goto out_free_e;
+		}
+
 		di = kmalloc(sizeof(*di) + pi->size, GFP_NOIO);
 		if (!di)
 			goto out_free_e;
diff --git a/drivers/block/drbd/drbd_worker.c b/drivers/block/drbd/drbd_worker.c
index 0697f99fed18..31e54960c5de 100644
--- a/drivers/block/drbd/drbd_worker.c
+++ b/drivers/block/drbd/drbd_worker.c
@@ -1174,8 +1174,8 @@ int w_e_end_csum_rs_req(struct drbd_work *w, int cancel)
 		 * introducing more locking mechanisms */
 		if (peer_device->connection->csums_tfm) {
 			digest_size = crypto_shash_digestsize(peer_device->connection->csums_tfm);
-			D_ASSERT(device, digest_size == di->digest_size);
-			digest = kmalloc(digest_size, GFP_NOIO);
+			if (digest_size == di->digest_size)
+				digest = kmalloc(digest_size, GFP_NOIO);
 		}
 		if (digest) {
 			drbd_csum_ee(peer_device->connection->csums_tfm, peer_req, digest);
@@ -1301,8 +1301,8 @@ int w_e_end_ov_reply(struct drbd_work *w, int cancel)
 		if (digest) {
 			drbd_csum_ee(peer_device->connection->verify_tfm, peer_req, digest);
 
-			D_ASSERT(device, digest_size == di->digest_size);
-			eq = !memcmp(digest, di->digest, digest_size);
+			eq = digest_size == di->digest_size &&
+			     !memcmp(digest, di->digest, digest_size);
 			kfree(digest);
 		}
 	}
-- 
2.39.5 (Apple Git-154)


      parent reply	other threads:[~2026-10-15 22:28 UTC|newest]

Thread overview: 3+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-10-15 22:27 [PATCH 0/2] drbd: validate payload sizes received from the peer Yibo Liu
2026-10-15 22:27 ` [PATCH 1/2] drbd: reject data replies whose size does not match the request Yibo Liu
2026-10-15 22:28 ` Yibo Liu [this message]

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20261015222800.85928-3-yiboliume@gmail.com \
    --to=yiboliume@gmail.com \
    --cc=axboe@kernel.dk \
    --cc=christoph.boehmwalder@linbit.com \
    --cc=drbd-dev@lists.linux.dev \
    --cc=lars.ellenberg@linbit.com \
    --cc=linux-block@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=philipp.reisner@linbit.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox

all inboxes | Powered by JetHome®