From: Michael Roth <mdroth@linux.vnet.ibm.com>
To: qemu-devel@nongnu.org
Cc: qemu-stable@nongnu.org
Subject: [PATCH 06/77] nbd/server: Avoid long error message assertions CVE-2020-10761
Date: Thu, 3 Sep 2020 15:58:24 -0500 [thread overview]
Message-ID: <20200903205935.27832-7-mdroth@linux.vnet.ibm.com> (raw)
In-Reply-To: <20200903205935.27832-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 02b1ed0801..20754e9ebc 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-09-03 21:56 UTC|newest]
Thread overview: 86+ messages / expand[flat|nested] mbox.gz Atom feed top
2020-09-03 20:58 [PATCH 00/77] Patch Round-up for stable 5.0.1, freeze on 2020-09-10 Michael Roth
2020-09-03 20:58 ` [PATCH 01/77] hostmem: don't use mbind() if host-nodes is empty Michael Roth
2020-09-03 20:58 ` [PATCH 02/77] target/arm: Clear tail in gvec_fmul_idx_*, gvec_fmla_idx_* Michael Roth
2020-09-03 20:58 ` [PATCH 03/77] qemu-nbd: Close inherited stderr Michael Roth
2020-09-03 20:58 ` [PATCH 04/77] 9p: Lock directory streams with a CoMutex Michael Roth
2020-09-03 20:58 ` [PATCH 05/77] net: Do not include a newline in the id of -nic devices Michael Roth
2020-09-03 20:58 ` Michael Roth [this message]
2020-09-03 20:58 ` [PATCH 07/77] virtio-balloon: fix free page hinting without an iothread Michael Roth
2020-09-03 20:58 ` [PATCH 08/77] virtio-balloon: fix free page hinting check on unrealize Michael Roth
2020-09-03 20:58 ` [PATCH 09/77] virtio-balloon: unref the iothread when unrealizing Michael Roth
2020-09-03 20:58 ` [PATCH 10/77] block: Call attention to truncation of long NBD exports Michael Roth
2020-09-03 20:58 ` [PATCH 11/77] 9pfs: local: ignore O_NOATIME if we don't have permissions Michael Roth
2020-09-03 20:58 ` [PATCH 12/77] 9pfs: include linux/limits.h for XATTR_SIZE_MAX Michael Roth
2020-09-03 20:58 ` [PATCH 13/77] xen-9pfs: Fix log messages of reply errors Michael Roth
2020-09-03 20:58 ` [PATCH 14/77] Revert "9p: init_in_iov_from_pdu can truncate the size" Michael Roth
2020-09-03 20:58 ` [PATCH 15/77] xen/9pfs: yield when there isn't enough room on the ring Michael Roth
2020-09-04 10:59 ` Christian Schoenebeck
2020-09-03 20:58 ` [PATCH 16/77] ati-vga: check mm_index before recursive call (CVE-2020-13800) Michael Roth
2020-09-03 20:58 ` [PATCH 17/77] es1370: check total frame count against current frame Michael Roth
2020-09-03 20:58 ` [PATCH 18/77] Fix tulip breakage Michael Roth
2020-09-03 20:58 ` [PATCH 19/77] iotests/283: Use consistent size for source and target Michael Roth
2020-09-03 20:58 ` [PATCH 20/77] virtiofsd: add --rlimit-nofile=NUM option Michael Roth
2020-09-03 20:58 ` [PATCH 21/77] virtiofsd: stay below fs.file-max sysctl value (CVE-2020-10717) Michael Roth
2020-09-03 20:58 ` [PATCH 22/77] net: use peer when purging queue in qemu_flush_or_purge_queue_packets() Michael Roth
2020-09-03 20:58 ` [PATCH 23/77] KVM: x86: believe what KVM says about WAITPKG Michael Roth
2020-09-03 20:58 ` [PATCH 24/77] aio-posix: don't duplicate fd handler deletion in fdmon_io_uring_destroy() Michael Roth
2020-09-03 20:58 ` [PATCH 25/77] aio-posix: disable fdmon-io_uring when GSource is used Michael Roth
2020-09-03 20:58 ` [PATCH 26/77] linux-user/strace.list: fix epoll_create{, 1} -strace output Michael Roth
2020-09-03 20:58 ` [PATCH 27/77] libqos: usb-hcd-ehci: use 32-bit write for config register Michael Roth
2020-09-03 20:58 ` [PATCH 28/77] libqos: pci-pc: use 32-bit write for EJ register Michael Roth
2020-09-03 20:58 ` [PATCH 29/77] memory: Revert "memory: accept mismatching sizes in memory_region_access_valid" Michael Roth
2020-09-03 20:58 ` [PATCH 30/77] hw/riscv: Allow 64 bit access to SiFive CLINT Michael Roth
2020-09-03 20:58 ` [PATCH 31/77] xhci: fix valid.max_access_size to access address registers Michael Roth
2020-09-03 20:58 ` [PATCH 32/77] acpi: accept byte and word access to core ACPI registers Michael Roth
2020-09-03 20:58 ` [PATCH 33/77] hw/display/artist: Unbreak size mismatch memory accesses Michael Roth
2020-09-03 20:58 ` [PATCH 34/77] hw/net/e1000e: Do not abort() on invalid PSRCTL register value Michael Roth
2020-09-03 20:58 ` [PATCH 35/77] virtiofsd: Whitelist fchmod Michael Roth
2020-09-03 20:58 ` [PATCH 36/77] hw/audio/gus: Fix registers 32-bit access Michael Roth
2020-09-03 20:58 ` [PATCH 37/77] net/virtio: Fix failover_replug_primary() return value regression Michael Roth
2020-09-03 20:58 ` [PATCH 38/77] error: Use error_reportf_err() where appropriate Michael Roth
2020-09-03 20:58 ` [PATCH 39/77] usb/dev-mtp: Fix Error double free after inotify failure Michael Roth
2020-09-03 20:58 ` [PATCH 40/77] nbd: Avoid off-by-one in long export name truncation Michael Roth
2020-09-03 20:58 ` [PATCH 41/77] chardev/tcp: Fix error message double free error Michael Roth
2020-09-03 20:59 ` [PATCH 42/77] qga: fix assert regression on guest-shutdown Michael Roth
2020-09-03 20:59 ` [PATCH 43/77] util: Introduce qemu_get_host_name() Michael Roth
2020-09-03 20:59 ` [PATCH 44/77] qga: Use qemu_get_host_name() instead of g_get_host_name() Michael Roth
2020-09-03 20:59 ` [PATCH 45/77] docs/orangepi: Add instructions for resizing SD image to power of two Michael Roth
2020-09-03 20:59 ` [PATCH 46/77] tests/acceptance/boot_linux: Tag tests using a SD card with 'device:sd' Michael Roth
2020-09-03 20:59 ` [PATCH 47/77] tests/acceptance: allow console interaction with specific VMs Michael Roth
2020-09-03 20:59 ` [PATCH 48/77] tests/acceptance: refactor boot_linux to allow code reuse Michael Roth
2020-09-03 20:59 ` [PATCH 49/77] tests/acceptance: refactor boot_linux_console test " Michael Roth
2020-09-03 20:59 ` [PATCH 50/77] tests/acceptance/boot_linux: Expand SD card image to power of 2 Michael Roth
2020-09-03 20:59 ` [PATCH 51/77] hw/sd/sdcard: Restrict Class 6 commands to SCSD cards Michael Roth
2020-09-03 20:59 ` [PATCH 52/77] hw/sd/sdcard: Simplify realize() a bit Michael Roth
2020-09-03 20:59 ` [PATCH 53/77] hw/sd/sdcard: Do not allow invalid SD card sizes Michael Roth
2020-09-03 20:59 ` [PATCH 54/77] hw/sd/sdcard: Update coding style to make checkpatch.pl happy Michael Roth
2020-09-03 20:59 ` [PATCH 55/77] hw/sd/sdcard: Do not switch to ReceivingData if address is invalid Michael Roth
2020-09-03 20:59 ` [PATCH 56/77] target/hppa: Free some temps in do_sub Michael Roth
2020-09-03 20:59 ` [PATCH 57/77] tpm: tpm_spapr: Exit on TPM backend failures Michael Roth
2020-09-03 20:59 ` [PATCH 58/77] tests: tpm: Skip over pcrUpdateCounter byte in result comparison Michael Roth
2020-09-03 20:59 ` [PATCH 59/77] qdev: Fix device_add DRIVER,help to print to monitor Michael Roth
2020-09-03 20:59 ` [PATCH 60/77] virtio-balloon: Prevent guest from starting a report when we didn't request one Michael Roth
2020-09-03 20:59 ` [PATCH 61/77] virtio-balloon: Add locking to prevent possible race when starting hinting Michael Roth
2020-09-03 20:59 ` [PATCH 62/77] virtio-balloon: always indicate S_DONE when migration fails Michael Roth
2020-09-03 20:59 ` [PATCH 63/77] linux-headers: update against Linux 5.7-rc3 Michael Roth
2020-09-03 20:59 ` [PATCH 64/77] virtio-balloon: Replace free page hinting references to 'report' with 'hint' Michael Roth
2020-09-03 20:59 ` [PATCH 65/77] virtio: list legacy-capable devices Michael Roth
2020-09-03 20:59 ` [PATCH 66/77] virtio: verify that legacy support is not accidentally on Michael Roth
2020-09-07 12:18 ` Cornelia Huck
2020-09-03 20:59 ` [PATCH 67/77] intel_iommu: Use correct shift for 256 bits qi descriptor Michael Roth
2020-09-03 20:59 ` [PATCH 68/77] virtio-pci: Changed vdev to proxy for VirtIO PCI BAR callbacks Michael Roth
2020-09-03 20:59 ` [PATCH 69/77] libvhost-user: Report descriptor index on panic Michael Roth
2020-09-03 20:59 ` [PATCH 70/77] Update OpenBIOS images to 7f28286f built from submodule Michael Roth
2020-09-03 20:59 ` [PATCH 71/77] migration/block-dirty-bitmap: fix dirty_bitmap_mig_before_vm_start Michael Roth
2020-09-03 20:59 ` [PATCH 72/77] block: Fix bdrv_aligned_p*v() for qiov_offset != 0 Michael Roth
2020-09-03 20:59 ` [PATCH 73/77] iotests/028: Add test for cross-base-EOF reads Michael Roth
2020-09-03 20:59 ` [PATCH 74/77] nbd: Fix large trim/zero requests Michael Roth
2020-09-03 20:59 ` [PATCH 75/77] virtio-net: align RSC fields with updated virtio-net header Michael Roth
2020-09-03 20:59 ` [PATCH 76/77] hw/arm/sbsa-ref: fix typo breaking PCIe IRQs Michael Roth
2020-09-03 20:59 ` [PATCH 77/77] usb: fix setup_len init (CVE-2020-14364) Michael Roth
2020-09-04 9:20 ` [PATCH 00/77] Patch Round-up for stable 5.0.1, freeze on 2020-09-10 Philippe Mathieu-Daudé
2020-09-10 18:16 ` Michael Roth
2020-09-10 19:29 ` Philippe Mathieu-Daudé
2020-09-10 20:11 ` Philippe Mathieu-Daudé
2020-09-04 13:17 ` Thomas Huth
2020-09-10 18:14 ` 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=20200903205935.27832-7-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).