Merge tag 'pull-request-2022-08-16' of https://gitlab.com/thuth/qemu into staging

* Fix a possible endless loop in USB XHCI code
* Minor fixes for the new readconfig test

# -----BEGIN PGP SIGNATURE-----
#
# iQJFBAABCAAvFiEEJ7iIR+7gJQEY8+q5LtnXdP5wLbUFAmL7aT8RHHRodXRoQHJl
# ZGhhdC5jb20ACgkQLtnXdP5wLbXm6w//TzGqEkzN6VeYqCgbI5ZuCcu3uL/X7KcO
# vsljTTYeJgE3IuT4RARk4d2/K8xD/mzyxMTHP5SrbCIYSOBY4OusJN55fytX46mb
# cdy3dHWbwaT7y8J+BLpwOg7om+oDp1Q2o1JxPY39BEi5T2C6PBHveDf9XxNv2n2j
# 9kwF0la7EmhmNoUgWyvf3dVoOFS3G4BTP1ZSvjcUNRuAxGLGZ8XOhZYw5zQ4MMTF
# OrNdVPmMDyLjAxpdO5dKItvTs8l0ioSXsbrNK+w2o58U1Wmczkn3BYcel2m+J14v
# XY9jtq9qUHjTmFRCCop0LYitkDvW+mAmptFsc94Y0ulc3JQ1KNvvjBIgNKZGRCkv
# Fw7xdArifc1TMpRdgNP1Gr88LXtSPEaPsHYMRy7AHcv2Abd9zrRm7JMa45mburzp
# jhUvFYCLN2iDgd78HClDAGuRLWAEaJDLkbvxHtJxGW8m9lHHwkrUeLm6uJMrSwu6
# 880O0/ayEz0jw5yDEDC/ooTbcWKgbpZ7KPREciSLTAPsC2orBrBIjlioY1YxfAMZ
# rrP7KvGggP7yWrOn4BKUWRo7NC2WPQ69nJQCTsXij4NlKsWAaJ3EgldKDcFgungk
# DsEm+FQhcDDfeOWN03dNxRxz8bFm1/HbSHgna5C5xnbQbQMiSPYVYWPjzK6E8kKO
# NgjewJS4E7E=
# =5xZ9
# -----END PGP SIGNATURE-----
# gpg: Signature made Tue 16 Aug 2022 04:54:07 AM CDT
# gpg:                using RSA key 27B88847EEE0250118F3EAB92ED9D774FE702DB5
# gpg:                issuer "thuth@redhat.com"
# gpg: Good signature from "Thomas Huth <th.huth@gmx.de>" [undefined]
# gpg:                 aka "Thomas Huth <thuth@redhat.com>" [undefined]
# gpg:                 aka "Thomas Huth <th.huth@posteo.de>" [unknown]
# gpg:                 aka "Thomas Huth <huth@tuxfamily.org>" [undefined]
# gpg: WARNING: This key is not certified with a trusted signature!
# gpg:          There is no indication that the signature belongs to the owner.
# Primary key fingerprint: 27B8 8847 EEE0 2501 18F3  EAB9 2ED9 D774 FE70 2DB5

* tag 'pull-request-2022-08-16' of https://gitlab.com/thuth/qemu:
  hw/usb/hcd-xhci: Fix unbounded loop in xhci_ring_chain_length() (CVE-2020-14394)
  tests/qtest: misc tweaks to readconfig

Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
diff --git a/hw/usb/hcd-xhci.c b/hw/usb/hcd-xhci.c
index 296cc6c..3c48b58 100644
--- a/hw/usb/hcd-xhci.c
+++ b/hw/usb/hcd-xhci.c
@@ -21,6 +21,7 @@
 
 #include "qemu/osdep.h"
 #include "qemu/timer.h"
+#include "qemu/log.h"
 #include "qemu/module.h"
 #include "qemu/queue.h"
 #include "migration/vmstate.h"
@@ -725,10 +726,14 @@
     bool control_td_set = 0;
     uint32_t link_cnt = 0;
 
-    while (1) {
+    do {
         TRBType type;
-        dma_memory_read(xhci->as, dequeue, &trb, TRB_SIZE,
-                        MEMTXATTRS_UNSPECIFIED);
+        if (dma_memory_read(xhci->as, dequeue, &trb, TRB_SIZE,
+                        MEMTXATTRS_UNSPECIFIED) != MEMTX_OK) {
+            qemu_log_mask(LOG_GUEST_ERROR, "%s: DMA memory access failed!\n",
+                          __func__);
+            return -1;
+        }
         le64_to_cpus(&trb.parameter);
         le32_to_cpus(&trb.status);
         le32_to_cpus(&trb.control);
@@ -762,7 +767,17 @@
         if (!control_td_set && !(trb.control & TRB_TR_CH)) {
             return length;
         }
-    }
+
+        /*
+         * According to the xHCI spec, Transfer Ring segments should have
+         * a maximum size of 64 kB (see chapter "6 Data Structures")
+         */
+    } while (length < TRB_LINK_LIMIT * 65536 / TRB_SIZE);
+
+    qemu_log_mask(LOG_GUEST_ERROR, "%s: exceeded maximum tranfer ring size!\n",
+                          __func__);
+
+    return -1;
 }
 
 static void xhci_er_reset(XHCIState *xhci, int v)
diff --git a/tests/qtest/readconfig-test.c b/tests/qtest/readconfig-test.c
index 2e604d7..c7a9b0c 100644
--- a/tests/qtest/readconfig-test.c
+++ b/tests/qtest/readconfig-test.c
@@ -33,13 +33,12 @@
     g_assert_cmpint(cfgfd, >=, 0);
 
     ret = qemu_write_full(cfgfd, cfgdata, strlen(cfgdata));
+    close(cfgfd);
     if (ret < 0) {
         unlink(cfgpath);
     }
     g_assert_cmpint(ret, ==, strlen(cfgdata));
 
-    close(cfgfd);
-
     args = g_strdup_printf("-nodefaults -machine none -readconfig %s", cfgpath);
 
     qts = qtest_init(args);
@@ -79,7 +78,7 @@
         "size = \"200\"";
 
     qts = qtest_init_with_config(cfgdata);
-   /* Test valid command */
+    /* Test valid command */
     resp = qtest_qmp(qts, "{ 'execute': 'query-memdev' }");
     test_x86_memdev_resp(qdict_get(resp, "return"));
     qobject_unref(resp);
@@ -96,7 +95,7 @@
 
     g_assert(res);
     v = qobject_input_visitor_new(res);
-    visit_type_SpiceInfo(v, "spcie", &spice, &error_abort);
+    visit_type_SpiceInfo(v, "spice", &spice, &error_abort);
 
     g_assert(spice);
     g_assert(spice->enabled);
@@ -114,7 +113,7 @@
         "unix = \"on\"\n";
 
     qts = qtest_init_with_config(cfgdata);
-   /* Test valid command */
+    /* Test valid command */
     resp = qtest_qmp(qts, "{ 'execute': 'query-spice' }");
     test_spice_resp(qdict_get(resp, "return"));
     qobject_unref(resp);
@@ -144,6 +143,7 @@
         if (g_str_equal(obj->name, "rng0") &&
             g_str_equal(obj->type, "child<rng-builtin>")) {
             seen_rng = true;
+            break;
         }
 
         tmp = tmp->next;
@@ -164,7 +164,7 @@
         "id = \"rng0\"\n";
 
     qts = qtest_init_with_config(cfgdata);
-   /* Test valid command */
+    /* Test valid command */
     resp = qtest_qmp(qts,
                      "{ 'execute': 'qom-list',"
                      "  'arguments': {'path': '/objects' }}");