From: Michael Roth <mdroth@linux.vnet.ibm.com>
To: qemu-devel@nongnu.org
Cc: qemu-stable@nongnu.org
Subject: [PATCH 74/78] nbd/server: Avoid long error message assertions CVE-2020-10761
Date: Tue, 16 Jun 2020 09:15:43 -0500 [thread overview]
Message-ID: <20200616141547.24664-75-mdroth@linux.vnet.ibm.com> (raw)
In-Reply-To: <20200616141547.24664-1-mdroth@linux.vnet.ibm.com>
From: Eric Blake <eblake@redhat.com>
Ever since commit 36683283 (v2.8), the server code asserts that error
strings sent to the client are well-formed per the protocol by not
exceeding the maximum string length of 4096. At the time the server
first started sending error messages, the assertion could not be
triggered, because messages were completely under our control.
However, over the years, we have added latent scenarios where a client
could trigger the server to attempt an error message that would
include the client's information if it passed other checks first:
- requesting NBD_OPT_INFO/GO on an export name that is not present
(commit 0cfae925 in v2.12 echoes the name)
- requesting NBD_OPT_LIST/SET_META_CONTEXT on an export name that is
not present (commit e7b1948d in v2.12 echoes the name)
At the time, those were still safe because we flagged names larger
than 256 bytes with a different message; but that changed in commit
93676c88 (v4.2) when we raised the name limit to 4096 to match the NBD
string limit. (That commit also failed to change the magic number
4096 in nbd_negotiate_send_rep_err to the just-introduced named
constant.) So with that commit, long client names appended to server
text can now trigger the assertion, and thus be used as a denial of
service attack against a server. As a mitigating factor, if the
server requires TLS, the client cannot trigger the problematic paths
unless it first supplies TLS credentials, and such trusted clients are
less likely to try to intentionally crash the server.
We may later want to further sanitize the user-supplied strings we
place into our error messages, such as scrubbing out control
characters, but that is less important to the CVE fix, so it can be a
later patch to the new nbd_sanitize_name.
Consideration was given to changing the assertion in
nbd_negotiate_send_rep_verr to instead merely log a server error and
truncate the message, to avoid leaving a latent path that could
trigger a future CVE DoS on any new error message. However, this
merely complicates the code for something that is already (correctly)
flagging coding errors, and now that we are aware of the long message
pitfall, we are less likely to introduce such errors in the future,
which would make such error handling dead code.
Reported-by: Xueqiang Wei <xuwei@redhat.com>
CC: qemu-stable@nongnu.org
Fixes: https://bugzilla.redhat.com/1843684 CVE-2020-10761
Fixes: 93676c88d7
Signed-off-by: Eric Blake <eblake@redhat.com>
Message-Id: <20200610163741.3745251-2-eblake@redhat.com>
Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
(cherry picked from commit 5c4fe018c025740fef4a0a4421e8162db0c3eefd)
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
---
nbd/server.c | 23 ++++++++++++++++++++---
tests/qemu-iotests/143 | 4 ++++
tests/qemu-iotests/143.out | 2 ++
3 files changed, 26 insertions(+), 3 deletions(-)
diff --git a/nbd/server.c b/nbd/server.c
index 24ebc1a805..d5b9df092c 100644
--- a/nbd/server.c
+++ b/nbd/server.c
@@ -217,7 +217,7 @@ nbd_negotiate_send_rep_verr(NBDClient *client, uint32_t type,
msg = g_strdup_vprintf(fmt, va);
len = strlen(msg);
- assert(len < 4096);
+ assert(len < NBD_MAX_STRING_SIZE);
trace_nbd_negotiate_send_rep_err(msg);
ret = nbd_negotiate_send_rep_len(client, type, len, errp);
if (ret < 0) {
@@ -231,6 +231,19 @@ nbd_negotiate_send_rep_verr(NBDClient *client, uint32_t type,
return 0;
}
+/*
+ * Return a malloc'd copy of @name suitable for use in an error reply.
+ */
+static char *
+nbd_sanitize_name(const char *name)
+{
+ if (strnlen(name, 80) < 80) {
+ return g_strdup(name);
+ }
+ /* XXX Should we also try to sanitize any control characters? */
+ return g_strdup_printf("%.80s...", name);
+}
+
/* Send an error reply.
* Return -errno on error, 0 on success. */
static int GCC_FMT_ATTR(4, 5)
@@ -595,9 +608,11 @@ static int nbd_negotiate_handle_info(NBDClient *client, Error **errp)
exp = nbd_export_find(name);
if (!exp) {
+ g_autofree char *sane_name = nbd_sanitize_name(name);
+
return nbd_negotiate_send_rep_err(client, NBD_REP_ERR_UNKNOWN,
errp, "export '%s' not present",
- name);
+ sane_name);
}
/* Don't bother sending NBD_INFO_NAME unless client requested it */
@@ -995,8 +1010,10 @@ static int nbd_negotiate_meta_queries(NBDClient *client,
meta->exp = nbd_export_find(export_name);
if (meta->exp == NULL) {
+ g_autofree char *sane_name = nbd_sanitize_name(export_name);
+
return nbd_opt_drop(client, NBD_REP_ERR_UNKNOWN, errp,
- "export '%s' not present", export_name);
+ "export '%s' not present", sane_name);
}
ret = nbd_opt_read(client, &nb_queries, sizeof(nb_queries), errp);
diff --git a/tests/qemu-iotests/143 b/tests/qemu-iotests/143
index f649b36195..d2349903b1 100755
--- a/tests/qemu-iotests/143
+++ b/tests/qemu-iotests/143
@@ -58,6 +58,10 @@ _send_qemu_cmd $QEMU_HANDLE \
$QEMU_IO_PROG -f raw -c quit \
"nbd+unix:///no_such_export?socket=$SOCK_DIR/nbd" 2>&1 \
| _filter_qemu_io | _filter_nbd
+# Likewise, with longest possible name permitted in NBD protocol
+$QEMU_IO_PROG -f raw -c quit \
+ "nbd+unix:///$(printf %4096d 1 | tr ' ' a)?socket=$SOCK_DIR/nbd" 2>&1 \
+ | _filter_qemu_io | _filter_nbd | sed 's/aaaa*aa/aa--aa/'
_send_qemu_cmd $QEMU_HANDLE \
"{ 'execute': 'quit' }" \
diff --git a/tests/qemu-iotests/143.out b/tests/qemu-iotests/143.out
index 1f4001c601..fc9c0a761f 100644
--- a/tests/qemu-iotests/143.out
+++ b/tests/qemu-iotests/143.out
@@ -5,6 +5,8 @@ QA output created by 143
{"return": {}}
qemu-io: can't open device nbd+unix:///no_such_export?socket=SOCK_DIR/nbd: Requested export not available
server reported: export 'no_such_export' not present
+qemu-io: can't open device nbd+unix:///aa--aa1?socket=SOCK_DIR/nbd: Requested export not available
+server reported: export 'aa--aa...' not present
{ 'execute': 'quit' }
{"return": {}}
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false, "reason": "host-qmp-quit"}}
--
2.17.1
next prev parent reply other threads:[~2020-06-16 14:58 UTC|newest]
Thread overview: 92+ messages / expand[flat|nested] mbox.gz Atom feed top
2020-06-16 14:14 [PATCH 00/78] Patch Round-up for stable 4.2.1, freeze on 2020-06-22 Michael Roth
2020-06-16 14:14 ` [PATCH 01/78] block/nbd: extract the common cleanup code Michael Roth
2020-06-16 14:14 ` [PATCH 02/78] block/nbd: fix memory leak in nbd_open() Michael Roth
2020-06-16 14:14 ` [PATCH 03/78] i386: Resolve CPU models to v1 by default Michael Roth
2020-06-16 14:14 ` [PATCH 04/78] qapi: better document NVMe blockdev @device parameter Michael Roth
2020-06-16 14:14 ` [PATCH 05/78] target/arm: ensure we use current exception state after SCR update Michael Roth
2020-06-16 14:14 ` [PATCH 06/78] block: Activate recursively even for already active nodes Michael Roth
2020-06-16 14:14 ` [PATCH 07/78] virtio-blk: fix out-of-bounds access to bitmap in notify_guest_bh Michael Roth
2020-06-16 14:14 ` [PATCH 08/78] numa: remove not needed check Michael Roth
2020-06-16 14:14 ` [PATCH 09/78] numa: properly check if numa is supported Michael Roth
2020-06-16 14:14 ` [PATCH 10/78] backup-top: Begin drain earlier Michael Roth
2020-06-16 14:14 ` [PATCH 11/78] arm/arm-powerctl: set NSACR.{CP11, CP10} bits in arm_set_cpu_on() Michael Roth
2020-06-16 14:14 ` [PATCH 12/78] arm/arm-powerctl: rebuild hflags after setting CP15 " Michael Roth
2020-06-16 14:14 ` [PATCH 13/78] hw/i386/pc: fix regression in parsing vga cmdline parameter Michael Roth
2020-06-16 14:14 ` [PATCH 14/78] tests/ide-test: Create a single unit-test covering more PRDT cases Michael Roth
2020-06-16 14:14 ` [PATCH 15/78] ide: Fix incorrect handling of some PRDTs in ide_dma_cb() Michael Roth
2020-06-16 14:14 ` [PATCH 16/78] target/arm: Set ISSIs16Bit in make_issinfo Michael Roth
2020-06-16 14:14 ` [PATCH 17/78] virtio: update queue size on guest write Michael Roth
2020-06-16 14:14 ` [PATCH 18/78] virtio-mmio: " Michael Roth
2020-06-16 14:14 ` [PATCH 19/78] virtio: add ability to delete vq through a pointer Michael Roth
2020-06-16 14:14 ` [PATCH 20/78] virtio: make virtio_delete_queue idempotent Michael Roth
2020-06-16 14:14 ` [PATCH 21/78] virtio: reset region cache when on queue deletion Michael Roth
2020-06-16 14:14 ` [PATCH 22/78] virtio-net: delete also control queue when TX/RX deleted Michael Roth
2020-06-16 14:14 ` [PATCH 23/78] intel_iommu: a fix to vtd_find_as_from_bus_num() Michael Roth
2020-06-16 14:14 ` [PATCH 24/78] intel_iommu: add present bit check for pasid table entries Michael Roth
2020-06-16 14:14 ` [PATCH 25/78] vfio/pci: Don't remove irqchip notifier if not registered Michael Roth
2020-06-16 14:14 ` [PATCH 26/78] qcow2-bitmaps: fix qcow2_can_store_new_dirty_bitmap Michael Roth
2020-06-16 14:14 ` [PATCH 27/78] dp8393x: Mask EOL bit from descriptor addresses Michael Roth
2020-06-16 14:14 ` [PATCH 28/78] dp8393x: Always use 32-bit accesses Michael Roth
2020-06-16 14:14 ` [PATCH 29/78] dp8393x: Clean up endianness hacks Michael Roth
2020-06-16 14:14 ` [PATCH 30/78] dp8393x: Have dp8393x_receive() return the packet size Michael Roth
2020-06-16 14:15 ` [PATCH 31/78] dp8393x: Update LLFA and CRDA registers from rx descriptor Michael Roth
2020-06-16 14:15 ` [PATCH 32/78] dp8393x: Clear RRRA command register bit only when appropriate Michael Roth
2020-06-16 14:15 ` [PATCH 33/78] dp8393x: Implement packet size limit and RBAE interrupt Michael Roth
2020-06-16 14:15 ` [PATCH 34/78] dp8393x: Don't clobber packet checksum Michael Roth
2020-06-16 14:15 ` [PATCH 35/78] dp8393x: Use long-word-aligned RRA pointers in 32-bit mode Michael Roth
2020-06-16 14:15 ` [PATCH 36/78] dp8393x: Pad frames to word or long word boundary Michael Roth
2020-06-16 14:15 ` [PATCH 37/78] dp8393x: Clear descriptor in_use field to release packet Michael Roth
2020-06-16 14:15 ` [PATCH 38/78] dp8393x: Always update RRA pointers and sequence numbers Michael Roth
2020-06-16 14:15 ` [PATCH 39/78] dp8393x: Don't reset Silicon Revision register Michael Roth
2020-06-16 14:15 ` [PATCH 40/78] dp8393x: Don't stop reception upon RBE interrupt assertion Michael Roth
2020-06-16 14:15 ` [PATCH 41/78] s390/sclp: improve special wait psw logic Michael Roth
2020-06-16 14:15 ` [PATCH 42/78] plugins/core: add missing break in cb_to_tcg_flags Michael Roth
2020-06-16 14:15 ` [PATCH 43/78] tcg: save vaddr temp for plugin usage Michael Roth
2020-06-16 14:15 ` [PATCH 44/78] qcow2: update_refcount(): Reset old_table_index after qcow2_cache_put() Michael Roth
2020-06-16 14:15 ` [PATCH 45/78] qcow2: Fix qcow2_alloc_cluster_abort() for external data file Michael Roth
2020-06-16 14:15 ` [PATCH 46/78] iotests: Test copy offloading with " Michael Roth
2020-06-16 14:15 ` [PATCH 47/78] qcow2: Fix alloc_cluster_abort() for pre-existing clusters Michael Roth
2020-06-16 14:15 ` [PATCH 48/78] iotests/026: Test EIO on preallocated zero cluster Michael Roth
2020-06-16 14:15 ` [PATCH 49/78] iotests/026: Test EIO on allocation in a data-file Michael Roth
2020-06-16 14:15 ` [PATCH 50/78] virtio: gracefully handle invalid region caches Michael Roth
2020-06-16 14:15 ` [PATCH 51/78] scsi/qemu-pr-helper: Fix out-of-bounds access to trnptid_list[] Michael Roth
2020-06-16 14:15 ` [PATCH 52/78] block/qcow2-threads: fix qcow2_decompress Michael Roth
2020-06-16 14:15 ` [PATCH 53/78] job: refactor progress to separate object Michael Roth
2020-06-16 14:15 ` [PATCH 54/78] block/block-copy: fix progress calculation Michael Roth
2020-06-16 14:15 ` [PATCH 55/78] target/ppc: Fix rlwinm on ppc64 Michael Roth
2020-06-16 14:15 ` [PATCH 56/78] block/io: fix bdrv_co_do_copy_on_readv Michael Roth
2020-06-16 14:15 ` [PATCH 57/78] compat: disable edid on correct virtio-gpu device Michael Roth
2020-06-16 14:15 ` [PATCH 58/78] qga: Installer: Wait for installation to finish Michael Roth
2020-06-16 14:15 ` [PATCH 59/78] qga-win: Handle VSS_E_PROVIDER_ALREADY_REGISTERED error Michael Roth
2020-06-16 14:15 ` [PATCH 60/78] qga-win: prevent crash when executing guest-file-read with large count Michael Roth
2020-06-16 14:15 ` [PATCH 61/78] qga: Fix undefined C behavior Michael Roth
2020-06-16 14:15 ` [PATCH 62/78] qemu-ga: document vsock-listen in the man page Michael Roth
2020-06-16 14:15 ` [PATCH 63/78] hw/i386/amd_iommu.c: Fix corruption of log events passed to guest Michael Roth
2020-06-16 14:15 ` [PATCH 64/78] tcg/i386: Fix INDEX_op_dup2_vec Michael Roth
2020-06-16 14:15 ` [PATCH 65/78] dump: Fix writing of ELF section Michael Roth
2020-06-16 14:15 ` [PATCH 66/78] xen-block: Fix double qlist remove and request leak Michael Roth
2020-06-16 14:15 ` [PATCH 67/78] vhost-user-gpu: Release memory returned by vu_queue_pop() with free() Michael Roth
2020-06-16 14:15 ` [PATCH 68/78] target/ppc: Fix mtmsr(d) L=1 variant that loses interrupts Michael Roth
2020-06-16 14:15 ` [PATCH 69/78] hostmem: don't use mbind() if host-nodes is empty Michael Roth
2020-06-16 14:15 ` [PATCH 70/78] target/arm: Clear tail in gvec_fmul_idx_*, gvec_fmla_idx_* Michael Roth
2020-06-16 14:15 ` [PATCH 71/78] qemu-nbd: Close inherited stderr Michael Roth
2020-06-16 14:15 ` [PATCH 72/78] 9p: Lock directory streams with a CoMutex Michael Roth
2020-06-16 15:14 ` Greg Kurz
2020-06-16 16:09 ` Christian Schoenebeck
2020-06-16 16:41 ` Greg Kurz
2020-06-16 22:46 ` Michael Roth
2020-06-18 13:47 ` Christian Schoenebeck
2020-06-16 14:15 ` [PATCH 73/78] net: Do not include a newline in the id of -nic devices Michael Roth
2020-06-16 14:15 ` Michael Roth [this message]
2020-06-16 14:15 ` [PATCH 75/78] virtio-balloon: fix free page hinting without an iothread Michael Roth
2020-06-16 14:15 ` [PATCH 76/78] virtio-balloon: fix free page hinting check on unrealize Michael Roth
2020-06-16 14:15 ` [PATCH 77/78] virtio-balloon: unref the iothread when unrealizing Michael Roth
2020-06-16 14:15 ` [PATCH 78/78] block: Call attention to truncation of long NBD exports Michael Roth
2020-06-17 14:39 ` [PATCH 00/78] Patch Round-up for stable 4.2.1, freeze on 2020-06-22 Cole Robinson
2020-06-17 15:54 ` Liam Merwick
2020-06-17 20:02 ` Karl Heubaum
2020-06-20 0:14 ` Finn Thain
2020-06-20 3:39 ` Finn Thain
2020-06-22 20:31 ` Michael Roth
2020-06-20 21:44 ` Bruce Rogers
2020-06-22 20:26 ` Michael Roth
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=20200616141547.24664-75-mdroth@linux.vnet.ibm.com \
--to=mdroth@linux.vnet.ibm.com \
--cc=qemu-devel@nongnu.org \
--cc=qemu-stable@nongnu.org \
/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;
as well as URLs for NNTP newsgroup(s).