From christoph.boehmwalder at linbit.com Fri Jul 10 12:27:28 2026 From: christoph.boehmwalder at linbit.com (Christoph =?utf-8?Q?B=C3=B6hmwalder?=) Date: Fri, 10 Jul 2026 12:27:28 +0200 Subject: [PATCH] drbd: reject data replies with an out-of-range payload size In-Reply-To: <20260710022837.3738461-1-michael.bommarito@gmail.com> References: <20260710022837.3738461-1-michael.bommarito@gmail.com> Message-ID: On Thu, Jul 09, 2026 at 10:28:37PM -0400, Michael Bommarito wrote: >recv_dless_read() receives a P_DATA_REPLY from a peer into the bio of an >outstanding read request. The peer-supplied payload length reaches it as >the signed int data_size, and two peer-controlled inputs can make it >negative. With a negotiated data-integrity-alg the digest length is >subtracted first, so a reply whose payload is smaller than the digest >underflows data_size. With no integrity algorithm (the default) data_size >is assigned from the unsigned h95/h100 wire length and drbdd() never >bounds it for a payload-carrying command, so a length above INT_MAX casts >it negative; this path needs no non-default feature. The bio receive loop >then computes expect = min_t(int, data_size, bv_len), which is negative, >and drbd_recv_all_warn(mapped, expect) receives with a size_t of SIZE_MAX >into the first mapped page. > >The sibling receive path read_in_block() is not affected: it uses an >unsigned size and rejects it against DRBD_MAX_BIO_SIZE before receiving. >Reject a data reply whose size is negative after the optional digest >subtraction, covering both triggers. > >Impact: a malicious or man-in-the-middle DRBD peer copies attacker-chosen >bytes past a bio page in the receiver, corrupting kernel memory. A node >that reads from its peer (a diskless node, or read-balancing to the peer) >is exposed in the default configuration; data-integrity-alg is not >required. > >Fixes: b411b3637fa7 ("The DRBD driver") >Cc: stable at vger.kernel.org >Assisted-by: Codex:gpt-5-5-xhigh >Assisted-by: Claude:claude-opus-4-8 >Signed-off-by: Michael Bommarito Looks correct, thanks. Note that DRBD usually chooses to trusts its peers by design, but I agree that memory corruption is a bad enough consequence that we should put the guard there regardless. Reviewed-by: Christoph B?hmwalder From christoph.boehmwalder at linbit.com Fri Jul 10 12:34:42 2026 From: christoph.boehmwalder at linbit.com (Christoph =?utf-8?Q?B=C3=B6hmwalder?=) Date: Fri, 10 Jul 2026 12:34:42 +0200 Subject: [PATCH] drbd: reject oversized DataReply before signed conversion In-Reply-To: References: Message-ID: On Tue, Jun 30, 2026 at 10:59:31AM +0000, Tianchu Chen wrote: >From: Tianchu Chen > >Discovered by Atuin - Automated Vulnerability Discovery Engine. > >Reject DataReply payload lengths that cannot fit in recv_dless_read()'s >signed size argument so a bogus remote peer cannot wrap the length negative >and turn it into a huge heap OOB-write. > >Fixes: b411b3637fa7 ("The DRBD driver") >Cc: stable at vger.kernel.org >Signed-off-by: Tianchu Chen This is similar to [0], but the mentioned patch is a more complete fix. There is also a case in recv_dless_read where data_size can underflow when a data-integrity-alg is configured. The other patch catches this case as well by placing the guard later, so I would prefer to apply that one instead of this. Thanks, Christoph [0] https://lore.kernel.org/all/20260710022837.3738461-1-michael.bommarito at gmail.com/ From christoph.boehmwalder at linbit.com Fri Jul 10 13:13:45 2026 From: christoph.boehmwalder at linbit.com (Christoph =?utf-8?Q?B=C3=B6hmwalder?=) Date: Fri, 10 Jul 2026 13:13:45 +0200 Subject: [PATCH] drbd: Fix potential NULL pointer dereference in _drbd_set_state() In-Reply-To: <20260625050016.12004-1-a.vatoropin@crpt.ru> References: <20260625050016.12004-1-a.vatoropin@crpt.ru> Message-ID: Thanks for your patch. On Thu, Jun 25, 2026 at 05:03:06AM +0000, ????????? ?????? wrote: >From: Andrey Vatoropin > >The connection pointer receives a value in the _drbd_set_state() >function, including through a call to the first_peer_device() function. >This function returns a pointer to a list element. If the list is empty, it >returns a NULL pointer, which is later assigned to the connection >pointer. Subsequently, this pointer will be dereferenced. Can the list actually be empty at this point? The peer_device is linked into the list in drbd_create_device(), before add_disk() and before the device is inserted into connection->peer_devices, so no state change can reach the device earlier. It is only unlinked again in drbd_destroy_device(), after the last kref to the device is gone. The connection itself is created together with the resource in drbd_adm_new_resource() and lives until the resource is destroyed. So for any device this function can be called on, first_peer_device() returns a valid peer_device. > >Add a NULL check for the connection pointer to avoid dereferencing an >invalid pointer. > >Found by Linux Verification Center (linuxtesting.org) with SVACE. > >Fixes: a6b32bc3cebd ("drbd: Introduce "peer_device" object between "device" and "connection"") >Cc: stable at vger.kernel.org >Signed-off-by: Andrey Vatoropin >--- > drivers/block/drbd/drbd_state.c | 5 +++++ > 1 file changed, 5 insertions(+) > >diff --git a/drivers/block/drbd/drbd_state.c b/drivers/block/drbd/drbd_state.c >index adcba7f1d8ea..ea982d48017e 100644 >--- a/drivers/block/drbd/drbd_state.c >+++ b/drivers/block/drbd/drbd_state.c >@@ -1281,6 +1281,11 @@ _drbd_set_state(struct drbd_device *device, union drbd_state ns, > if (rv < SS_SUCCESS) > return rv; > >+ if (!connection) { >+ drbd_err(device, "No connection to peer, aborting!\n"); >+ return SS_ALREADY_STANDALONE; >+ } >+ Also, even if the condition could happen, its handling here would be wrong. Since this check happens before handling hard state changes, those could potentially be skipped, which is not allowed. For example, after a local I/O error (drbd_chk_io_error), if this condition would trigger, the detach state change would be silently skipped. So in that circumstance, this patch would be actively harmful. Also, SS_ALREADY_STANDALONE would map to the error message "Can not disconnect a StandAlone device", which does not make any sense in this context. > if (!(flags & CS_HARD)) { > /* pre-state-change checks ; only look at ns */ > /* See drbd_state_sw_errors in drbd_strings.c */ >-- >2.43.0 In summary, unless I missed something major: NAK. Thanks, Christoph From axboe at kernel.dk Fri Jul 10 17:09:05 2026 From: axboe at kernel.dk (Jens Axboe) Date: Fri, 10 Jul 2026 09:09:05 -0600 Subject: [PATCH] drbd: reject data replies with an out-of-range payload size In-Reply-To: <20260710022837.3738461-1-michael.bommarito@gmail.com> References: <20260710022837.3738461-1-michael.bommarito@gmail.com> Message-ID: <178369614511.284240.12733294719230479134.b4-ty@b4> On Thu, 09 Jul 2026 22:28:37 -0400, Michael Bommarito wrote: > recv_dless_read() receives a P_DATA_REPLY from a peer into the bio of an > outstanding read request. The peer-supplied payload length reaches it as > the signed int data_size, and two peer-controlled inputs can make it > negative. With a negotiated data-integrity-alg the digest length is > subtracted first, so a reply whose payload is smaller than the digest > underflows data_size. With no integrity algorithm (the default) data_size > is assigned from the unsigned h95/h100 wire length and drbdd() never > bounds it for a payload-carrying command, so a length above INT_MAX casts > it negative; this path needs no non-default feature. The bio receive loop > then computes expect = min_t(int, data_size, bv_len), which is negative, > and drbd_recv_all_warn(mapped, expect) receives with a size_t of SIZE_MAX > into the first mapped page. > > [...] Applied, thanks! [1/1] drbd: reject data replies with an out-of-range payload size commit: bd910a7660d280595ef94cb6d193951d855d330f Best regards, -- Jens Axboe