CVE-2025-47711 denial of service attack by client sending maximum size block
status CVE-2025-47712 denial of service attack by client sending large unaligned size block status resolves: RHEL-95814
This commit is contained in:
parent
83a3fe53b0
commit
d1cbcbdf54
170
0041-server-Fix-off-by-one-for-maximum-block_status-lengt.patch
Normal file
170
0041-server-Fix-off-by-one-for-maximum-block_status-lengt.patch
Normal file
@ -0,0 +1,170 @@
|
||||
From 4d7da0f8b01f70ceddfd3d10345bf08284591938 Mon Sep 17 00:00:00 2001
|
||||
From: Eric Blake <eblake@redhat.com>
|
||||
Date: Tue, 22 Apr 2025 17:01:12 -0500
|
||||
Subject: [PATCH] server: Fix off-by-one for maximum block_status length
|
||||
[CVE-2025-47711]
|
||||
|
||||
There has been an off-by-one bug in the code for .extents since the
|
||||
introduction of that callback. Remember, internally the code allows
|
||||
plugins to report on extents with 64-bit lengths, but the protocol
|
||||
only supports 32-bit block status calls (nbdkit will need to create
|
||||
plugin version 3 before it can support NBD's newer 64-bit block
|
||||
status). As such, the server loop intentionally truncates a plugin's
|
||||
large extent to 2**32-1 bytes. But in the process of checking whether
|
||||
the loop should exit early, or if any additional extents should be
|
||||
reported to the client, the server used 'pos > offset+count' instead
|
||||
of >=, which is one byte too far. If the client has requested exactly
|
||||
2**32-1 bytes, and the plugin's first extent has that same length, the
|
||||
code erroneously proceeds on to the plugin's second extent. Worse, if
|
||||
the plugin's first extent has 2**32 bytes or more, it was truncated to
|
||||
2**31-1 bytes, but not completely handled, and the failure to exit the
|
||||
loop early means that the server then fails the assertion:
|
||||
|
||||
nbdkit: ../../server/protocol.c:505: extents_to_block_descriptors:
|
||||
Assertion `e.length <= length' failed.
|
||||
|
||||
The single-byte fix addresses both symptoms, while the added test
|
||||
demonstrates both when run on older nbdkit (the protocol violation
|
||||
when the plugin returns 2**32-1 bytes in the first extent, and the
|
||||
assertion failure when the plugin returns 2**32 or more bytes in the
|
||||
first extent).
|
||||
|
||||
The problem can only be triggered by a client request for 2**32-1
|
||||
bytes; anything smaller is immune. The problem also does not occur
|
||||
for plugins that do not return extents information beyond the client's
|
||||
request, or if the first extent is smaller than the client's request.
|
||||
|
||||
The ability to cause the server to die from an assertion failure can
|
||||
be used as a denial of service attack against other clients.
|
||||
Mitigations: if you require the use of TLS, then you can ensure that
|
||||
you only have trusted clients that won't trigger a block status call
|
||||
of length 2**32-1 bytes. Also, you can use "--filter=blocksize-policy
|
||||
blocksize-minimum=512" to reject block status attempts from clients
|
||||
that are not sector-aligned.
|
||||
|
||||
Fixes: 26455d45 ('server: protocol: Implement Block Status "base:allocation".', v1.11.10)
|
||||
Reported-by: Nikolay Ivanets <stenavin@gmail.com>
|
||||
Signed-off-by: Eric Blake <eblake@redhat.com>
|
||||
Message-ID: <20250423211953.GR1450@redhat.com>
|
||||
Reviewed-by: Richard W.M. Jones <rjones@redhat.com>
|
||||
(cherry picked from commit e6f96bd1b77c0cc927ce6aeff650b52238304f39)
|
||||
---
|
||||
server/protocol.c | 2 +-
|
||||
tests/Makefile.am | 2 ++
|
||||
tests/test-eval-extents.sh | 71 ++++++++++++++++++++++++++++++++++++++
|
||||
3 files changed, 74 insertions(+), 1 deletion(-)
|
||||
create mode 100755 tests/test-eval-extents.sh
|
||||
|
||||
diff --git a/server/protocol.c b/server/protocol.c
|
||||
index d428bfc8..b4b1c162 100644
|
||||
--- a/server/protocol.c
|
||||
+++ b/server/protocol.c
|
||||
@@ -499,7 +499,7 @@ extents_to_block_descriptors (struct nbdkit_extents *extents,
|
||||
(*nr_blocks)++;
|
||||
|
||||
pos += length;
|
||||
- if (pos > offset + count) /* this must be the last block */
|
||||
+ if (pos >= offset + count) /* this must be the last block */
|
||||
break;
|
||||
|
||||
/* If we reach here then we must have consumed this whole
|
||||
diff --git a/tests/Makefile.am b/tests/Makefile.am
|
||||
index eed96d28..9f9885b4 100644
|
||||
--- a/tests/Makefile.am
|
||||
+++ b/tests/Makefile.am
|
||||
@@ -824,6 +824,7 @@ TESTS += \
|
||||
test-eval.sh \
|
||||
test-eval-file.sh \
|
||||
test-eval-exports.sh \
|
||||
+ test-eval-extents.sh \
|
||||
test-eval-cache.sh \
|
||||
test-eval-dump-plugin.sh \
|
||||
test-eval-disconnect.sh \
|
||||
@@ -832,6 +833,7 @@ EXTRA_DIST += \
|
||||
test-eval.sh \
|
||||
test-eval-file.sh \
|
||||
test-eval-exports.sh \
|
||||
+ test-eval-extents.sh \
|
||||
test-eval-cache.sh \
|
||||
test-eval-dump-plugin.sh \
|
||||
test-eval-disconnect.sh \
|
||||
diff --git a/tests/test-eval-extents.sh b/tests/test-eval-extents.sh
|
||||
new file mode 100755
|
||||
index 00000000..92b503e6
|
||||
--- /dev/null
|
||||
+++ b/tests/test-eval-extents.sh
|
||||
@@ -0,0 +1,71 @@
|
||||
+#!/usr/bin/env bash
|
||||
+# nbdkit
|
||||
+# Copyright Red Hat
|
||||
+#
|
||||
+# Redistribution and use in source and binary forms, with or without
|
||||
+# modification, are permitted provided that the following conditions are
|
||||
+# met:
|
||||
+#
|
||||
+# * Redistributions of source code must retain the above copyright
|
||||
+# notice, this list of conditions and the following disclaimer.
|
||||
+#
|
||||
+# * Redistributions in binary form must reproduce the above copyright
|
||||
+# notice, this list of conditions and the following disclaimer in the
|
||||
+# documentation and/or other materials provided with the distribution.
|
||||
+#
|
||||
+# * Neither the name of Red Hat nor the names of its contributors may be
|
||||
+# used to endorse or promote products derived from this software without
|
||||
+# specific prior written permission.
|
||||
+#
|
||||
+# THIS SOFTWARE IS PROVIDED BY RED HAT AND CONTRIBUTORS ''AS IS'' AND
|
||||
+# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
|
||||
+# THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
|
||||
+# PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL RED HAT OR
|
||||
+# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
|
||||
+# USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
+# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
+# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
|
||||
+# OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
+# SUCH DAMAGE.
|
||||
+
|
||||
+source ./functions.sh
|
||||
+set -e
|
||||
+set -x
|
||||
+
|
||||
+requires_run
|
||||
+requires_plugin eval
|
||||
+requires_nbdsh_uri
|
||||
+requires nbdsh --base-allocation --version
|
||||
+
|
||||
+files="eval-extents.out"
|
||||
+rm -f $files
|
||||
+cleanup_fn rm -f $files
|
||||
+
|
||||
+# Trigger an off-by-one bug introduced in v1.11.10 and fixed in v1.43.7
|
||||
+export script='
|
||||
+def f(context, offset, extents, status):
|
||||
+ print(extents)
|
||||
+
|
||||
+# First, probe where the server should return 2 extents.
|
||||
+h.block_status(2**32-1, 2, f)
|
||||
+
|
||||
+# Next, probe where the server has exactly 2**32-1 bytes in its first extent.
|
||||
+h.block_status(2**32-1, 1, f)
|
||||
+
|
||||
+# Now, probe where the first extent has to be truncated.
|
||||
+h.block_status(2**32-1, 0, f)
|
||||
+'
|
||||
+nbdkit eval \
|
||||
+ get_size='echo 5G' \
|
||||
+ pread='dd if=/dev/zero count=$3 iflag=count_bytes' \
|
||||
+ extents='echo 0 4G 1; echo 4G 1G 2' \
|
||||
+ --run 'nbdsh --base-allocation --uri "$uri" -c "$script"' \
|
||||
+ > eval-extents.out
|
||||
+cat eval-extents.out
|
||||
+diff -u - eval-extents.out <<EOF
|
||||
+[4294967294, 1, 1073741824, 2]
|
||||
+[4294967295, 1]
|
||||
+[4294967295, 1]
|
||||
+EOF
|
||||
--
|
||||
2.47.1
|
||||
|
163
0042-blocksize-Fix-32-bit-overflow-in-.extents-CVE-2025-4.patch
Normal file
163
0042-blocksize-Fix-32-bit-overflow-in-.extents-CVE-2025-4.patch
Normal file
@ -0,0 +1,163 @@
|
||||
From fbca97afb4139f4ae42113f1a91ba595d332d07c Mon Sep 17 00:00:00 2001
|
||||
From: Eric Blake <eblake@redhat.com>
|
||||
Date: Tue, 22 Apr 2025 19:53:39 -0500
|
||||
Subject: [PATCH] blocksize: Fix 32-bit overflow in .extents [CVE-2025-47712]
|
||||
|
||||
If the original request is larger than 2**32 - minblock, then we were
|
||||
calling nbdkit_extents_aligned() with a count that rounded up then
|
||||
overflowed to 0 instead of the intended 4G because of overflowing a
|
||||
32-bit type, which in turn causes an assertion failure:
|
||||
|
||||
nbdkit: ../../server/backend.c:814: backend_extents: Assertion `backend_valid_range (c, offset, count)' failed.
|
||||
|
||||
The fix is to force the rounding to be in a 64-bit type from the
|
||||
get-go.
|
||||
|
||||
The ability for a well-behaved client to cause the server to die from
|
||||
an assertion failure can be used as a denial of service attack against
|
||||
other clients. Mitigations: if you requrire the use of TLS, then you
|
||||
can ensure that you only have trusted clients that won't trigger a
|
||||
block status call that large. Also, the problem only occurs when
|
||||
using the blocksize filter, although setting the filter's maxlen
|
||||
parameter to a smaller value than its default of 2**32-1 does not
|
||||
help.
|
||||
|
||||
Fixes: 2680be00 ('blocksize: Fix .extents when plugin changes type within minblock', v1.21.16)
|
||||
Signed-off-by: Eric Blake <eblake@redhat.com>
|
||||
Message-ID: <20250423210917.1784789-3-eblake@redhat.com>
|
||||
Reviewed-by: Richard W.M. Jones <rjones@redhat.com>
|
||||
(cherry picked from commit a486f88d1eea653ea88b0bf8804c4825dab25ec7)
|
||||
---
|
||||
filters/blocksize/blocksize.c | 5 +-
|
||||
tests/Makefile.am | 2 +
|
||||
tests/test-blocksize-extents-overflow.sh | 83 ++++++++++++++++++++++++
|
||||
3 files changed, 88 insertions(+), 2 deletions(-)
|
||||
create mode 100755 tests/test-blocksize-extents-overflow.sh
|
||||
|
||||
diff --git a/filters/blocksize/blocksize.c b/filters/blocksize/blocksize.c
|
||||
index 09195cea..e5c8b744 100644
|
||||
--- a/filters/blocksize/blocksize.c
|
||||
+++ b/filters/blocksize/blocksize.c
|
||||
@@ -482,8 +482,9 @@ blocksize_extents (nbdkit_next *next,
|
||||
return -1;
|
||||
}
|
||||
|
||||
- if (nbdkit_extents_aligned (next, MIN (ROUND_UP (count, h->minblock),
|
||||
- h->maxlen),
|
||||
+ if (nbdkit_extents_aligned (next,
|
||||
+ MIN (ROUND_UP ((uint64_t) count, h->minblock),
|
||||
+ h->maxlen),
|
||||
ROUND_DOWN (offset, h->minblock), flags,
|
||||
h->minblock, extents2, err) == -1)
|
||||
return -1;
|
||||
diff --git a/tests/Makefile.am b/tests/Makefile.am
|
||||
index 9f9885b4..428b65e2 100644
|
||||
--- a/tests/Makefile.am
|
||||
+++ b/tests/Makefile.am
|
||||
@@ -1592,12 +1592,14 @@ test_layers_filter3_la_LIBADD = $(IMPORT_LIBRARY_ON_WINDOWS)
|
||||
TESTS += \
|
||||
test-blocksize.sh \
|
||||
test-blocksize-extents.sh \
|
||||
+ test-blocksize-extents-overflow.sh \
|
||||
test-blocksize-default.sh \
|
||||
test-blocksize-sharding.sh \
|
||||
$(NULL)
|
||||
EXTRA_DIST += \
|
||||
test-blocksize.sh \
|
||||
test-blocksize-extents.sh \
|
||||
+ test-blocksize-extents-overflow.sh \
|
||||
test-blocksize-default.sh \
|
||||
test-blocksize-sharding.sh \
|
||||
$(NULL)
|
||||
diff --git a/tests/test-blocksize-extents-overflow.sh b/tests/test-blocksize-extents-overflow.sh
|
||||
new file mode 100755
|
||||
index 00000000..844c3999
|
||||
--- /dev/null
|
||||
+++ b/tests/test-blocksize-extents-overflow.sh
|
||||
@@ -0,0 +1,83 @@
|
||||
+#!/usr/bin/env bash
|
||||
+# nbdkit
|
||||
+# Copyright Red Hat
|
||||
+#
|
||||
+# Redistribution and use in source and binary forms, with or without
|
||||
+# modification, are permitted provided that the following conditions are
|
||||
+# met:
|
||||
+#
|
||||
+# * Redistributions of source code must retain the above copyright
|
||||
+# notice, this list of conditions and the following disclaimer.
|
||||
+#
|
||||
+# * Redistributions in binary form must reproduce the above copyright
|
||||
+# notice, this list of conditions and the following disclaimer in the
|
||||
+# documentation and/or other materials provided with the distribution.
|
||||
+#
|
||||
+# * Neither the name of Red Hat nor the names of its contributors may be
|
||||
+# used to endorse or promote products derived from this software without
|
||||
+# specific prior written permission.
|
||||
+#
|
||||
+# THIS SOFTWARE IS PROVIDED BY RED HAT AND CONTRIBUTORS ''AS IS'' AND
|
||||
+# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
|
||||
+# THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
|
||||
+# PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL RED HAT OR
|
||||
+# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
|
||||
+# USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
+# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
+# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
|
||||
+# OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
+# SUCH DAMAGE.
|
||||
+
|
||||
+# Demonstrate a fix for a bug where blocksize overflowed 32 bits
|
||||
+
|
||||
+source ./functions.sh
|
||||
+set -e
|
||||
+set -x
|
||||
+
|
||||
+requires_run
|
||||
+requires_plugin eval
|
||||
+requires_nbdsh_uri
|
||||
+requires nbdsh --base-allocation --version
|
||||
+
|
||||
+# Script a sparse server that requires 512-byte aligned requests.
|
||||
+exts='
|
||||
+if test $(( ($3|$4) & 511 )) != 0; then
|
||||
+ echo "EINVAL request unaligned" 2>&1
|
||||
+ exit 1
|
||||
+fi
|
||||
+echo 0 5G 0
|
||||
+'
|
||||
+
|
||||
+# We also need an nbdsh script to parse all extents, coalescing adjacent
|
||||
+# types for simplicity.
|
||||
+# FIXME: Once nbdkit plugin version 3 allows 64-bit block extents, run
|
||||
+# this test twice, once for each bit size (32-bit needs 2 extents, 64-bit
|
||||
+# will get the same result with only 1 extent).
|
||||
+export script='
|
||||
+size = h.get_size()
|
||||
+offs = 0
|
||||
+entries = []
|
||||
+def f(metacontext, offset, e, err):
|
||||
+ global entries
|
||||
+ global offs
|
||||
+ assert offs == offset
|
||||
+ for length, flags in zip(*[iter(e)] * 2):
|
||||
+ if entries and flags == entries[-1][1]:
|
||||
+ entries[-1] = (entries[-1][0] + length, flags)
|
||||
+ else:
|
||||
+ entries.append((length, flags))
|
||||
+ offs = offs + length
|
||||
+
|
||||
+# Test a loop over the entire device
|
||||
+while offs < size:
|
||||
+ len = min(size - offs, 2**32-1)
|
||||
+ h.block_status(len, offs, f)
|
||||
+assert entries == [(5 * 2**30, 0)]
|
||||
+'
|
||||
+
|
||||
+# Now run everything
|
||||
+nbdkit --filter=blocksize eval minblock=512 \
|
||||
+ get_size='echo 5G' pread='exit 1' extents="$exts" \
|
||||
+ --run 'nbdsh --base-allocation -u "$uri" -c "$script"'
|
||||
--
|
||||
2.47.1
|
||||
|
11
nbdkit.spec
11
nbdkit.spec
@ -56,7 +56,7 @@
|
||||
|
||||
Name: nbdkit
|
||||
Version: 1.38.5
|
||||
Release: 9%{?dist}
|
||||
Release: 10%{?dist}
|
||||
Summary: NBD server
|
||||
|
||||
License: BSD-3-Clause
|
||||
@ -121,6 +121,8 @@ Patch0037: 0037-vddk-stats-Use-us-instead-of-Unicode-s-for-microseco.patch
|
||||
Patch0038: 0038-vddk-stats-Line-up-the-columns-correctly.patch
|
||||
Patch0039: 0039-vddk-stats-Record-the-byte-count-of-each-QueryAlloca.patch
|
||||
Patch0040: 0040-vddk-stats-Collect-elapsed-time-for-ReadAsync-and-Wr.patch
|
||||
Patch0041: 0041-server-Fix-off-by-one-for-maximum-block_status-lengt.patch
|
||||
Patch0042: 0042-blocksize-Fix-32-bit-overflow-in-.extents-CVE-2025-4.patch
|
||||
|
||||
# For automatic RPM Provides generation.
|
||||
# See: https://rpm-software-management.github.io/rpm/manual/dependency_generators.html
|
||||
@ -1539,6 +1541,13 @@ fi
|
||||
|
||||
|
||||
%changelog
|
||||
* Mon Jun 09 2025 Richard W.M. Jones <rjones@redhat.com> - 1.38.5-10
|
||||
- CVE-2025-47711 denial of service attack by client sending maximum size block
|
||||
status
|
||||
- CVE-2025-47712 denial of service attack by client sending large unaligned
|
||||
size block status
|
||||
resolves: RHEL-95814
|
||||
|
||||
* Sun Jun 08 2025 Richard W.M. Jones <rjones@redhat.com> - 1.38.5-9
|
||||
- vddk: Improve statistics
|
||||
related: RHEL-94823
|
||||
|
Loading…
Reference in New Issue
Block a user