diff -Nru qemu-2.5+dfsg/debian/changelog qemu-2.5+dfsg/debian/changelog --- qemu-2.5+dfsg/debian/changelog 2020-09-15 14:10:16.000000000 +0000 +++ qemu-2.5+dfsg/debian/changelog 2020-09-21 13:50:56.000000000 +0000 @@ -1,3 +1,9 @@ +qemu (1:2.5+dfsg-5ubuntu10.47) xenial; urgency=medium + + * d/p/u/lp-1894942-*: fix virtio-ccw host/guest notification (LP: #1894942) + + -- Christian Ehrhardt Mon, 21 Sep 2020 15:50:56 +0200 + qemu (1:2.5+dfsg-5ubuntu10.46) xenial-security; urgency=medium * SECURITY UPDATE: out-of-bounds read/write in USB emulator diff -Nru qemu-2.5+dfsg/debian/patches/series qemu-2.5+dfsg/debian/patches/series --- qemu-2.5+dfsg/debian/patches/series 2020-09-15 14:09:40.000000000 +0000 +++ qemu-2.5+dfsg/debian/patches/series 2020-09-21 13:50:56.000000000 +0000 @@ -329,3 +329,5 @@ CVE-2020-12829-7.patch CVE-2020-14364-pre.patch CVE-2020-14364.patch +ubuntu/lp-1894942-virtio-ccw-fix-virtio_set_ind_atomic.patch +ubuntu/lp-1894942-s390x-pci-fix-set_ind_atomic.patch diff -Nru qemu-2.5+dfsg/debian/patches/ubuntu/lp-1894942-s390x-pci-fix-set_ind_atomic.patch qemu-2.5+dfsg/debian/patches/ubuntu/lp-1894942-s390x-pci-fix-set_ind_atomic.patch --- qemu-2.5+dfsg/debian/patches/ubuntu/lp-1894942-s390x-pci-fix-set_ind_atomic.patch 1970-01-01 00:00:00.000000000 +0000 +++ qemu-2.5+dfsg/debian/patches/ubuntu/lp-1894942-s390x-pci-fix-set_ind_atomic.patch 2020-09-21 13:50:56.000000000 +0000 @@ -0,0 +1,67 @@ +From 45175361f1bfc2d3ccdcb4b22570c2352f3de754 Mon Sep 17 00:00:00 2001 +From: Halil Pasic +Date: Tue, 16 Jun 2020 06:50:35 +0200 +Subject: [PATCH] s390x/pci: fix set_ind_atomic + +The atomic_cmpxchg() loop is broken because we occasionally end up with +old and _old having different values (a legit compiler can generate code +that accessed *ind_addr again to pick up a value for _old instead of +using the value of old that was already fetched according to the +rules of the abstract machine). This means the underlying CS instruction +may use a different old (_old) than the one we intended to use if +atomic_cmpxchg() performed the xchg part. + +Let us use volatile to force the rules of the abstract machine for +accesses to *ind_addr. Let us also rewrite the loop so, we that the +new old is used to compute the new desired value if the xchg part +is not performed. + +Fixes: 8cba80c3a0 ("s390: Add PCI bus support") +Reported-by: Christian Borntraeger +Signed-off-by: Halil Pasic +Reviewed-by: Christian Borntraeger +Message-Id: <20200616045035.51641-3-pasic@linux.ibm.com> +Signed-off-by: Cornelia Huck + +Origin: backport, https://git.qemu.org/?p=qemu.git;a=commit;h=45175361f1 +Bug-Ubuntu: https://bugs.launchpad.net/bugs/1894942 +Last-Update: 2020-09-21 + +--- + hw/s390x/s390-pci-bus.c | 16 +++++++++------- + 1 file changed, 9 insertions(+), 7 deletions(-) + +--- a/hw/s390x/s390-pci-bus.c ++++ b/hw/s390x/s390-pci-bus.c +@@ -637,22 +637,24 @@ static AddressSpace *s390_pci_dma_iommu( + + static uint8_t set_ind_atomic(uint64_t ind_loc, uint8_t to_be_set) + { +- uint8_t ind_old, ind_new; ++ uint8_t expected, actual; + hwaddr len = 1; +- uint8_t *ind_addr; ++ /* avoid multiple fetches */ ++ uint8_t volatile *ind_addr; + + ind_addr = cpu_physical_memory_map(ind_loc, &len, 1); + if (!ind_addr) { + s390_pci_generate_error_event(ERR_EVENT_AIRERR, 0, 0, 0, 0); + return -1; + } ++ actual = *ind_addr; + do { +- ind_old = *ind_addr; +- ind_new = ind_old | to_be_set; +- } while (atomic_cmpxchg(ind_addr, ind_old, ind_new) != ind_old); +- cpu_physical_memory_unmap(ind_addr, len, 1, len); ++ expected = actual; ++ actual = atomic_cmpxchg(ind_addr, expected, expected | to_be_set); ++ } while (actual != expected); ++ cpu_physical_memory_unmap((void *)ind_addr, len, 1, len); + +- return ind_old; ++ return actual; + } + + static void s390_msi_ctrl_write(void *opaque, hwaddr addr, uint64_t data, diff -Nru qemu-2.5+dfsg/debian/patches/ubuntu/lp-1894942-virtio-ccw-fix-virtio_set_ind_atomic.patch qemu-2.5+dfsg/debian/patches/ubuntu/lp-1894942-virtio-ccw-fix-virtio_set_ind_atomic.patch --- qemu-2.5+dfsg/debian/patches/ubuntu/lp-1894942-virtio-ccw-fix-virtio_set_ind_atomic.patch 1970-01-01 00:00:00.000000000 +0000 +++ qemu-2.5+dfsg/debian/patches/ubuntu/lp-1894942-virtio-ccw-fix-virtio_set_ind_atomic.patch 2020-09-21 13:50:56.000000000 +0000 @@ -0,0 +1,68 @@ +From 1a8242f7c3f53341dd66253b142ecd06ce1d2a97 Mon Sep 17 00:00:00 2001 +From: Halil Pasic +Date: Tue, 16 Jun 2020 06:50:34 +0200 +Subject: [PATCH] virtio-ccw: fix virtio_set_ind_atomic + +The atomic_cmpxchg() loop is broken because we occasionally end up with +old and _old having different values (a legit compiler can generate code +that accessed *ind_addr again to pick up a value for _old instead of +using the value of old that was already fetched according to the +rules of the abstract machine). This means the underlying CS instruction +may use a different old (_old) than the one we intended to use if +atomic_cmpxchg() performed the xchg part. + +Let us use volatile to force the rules of the abstract machine for +accesses to *ind_addr. Let us also rewrite the loop so, we that the +new old is used to compute the new desired value if the xchg part +is not performed. + +Fixes: 7e7494627f ("s390x/virtio-ccw: Adapter interrupt support.") +Reported-by: Andre Wild +Signed-off-by: Halil Pasic +Reviewed-by: Christian Borntraeger +Message-Id: <20200616045035.51641-2-pasic@linux.ibm.com> +Signed-off-by: Cornelia Huck + +Origin: backport, https://git.qemu.org/?p=qemu.git;a=commit;h=1a8242f7c3 +Bug-Ubuntu: https://bugs.launchpad.net/bugs/1894942 +Last-Update: 2020-09-21 + +--- + hw/s390x/virtio-ccw.c | 18 ++++++++++-------- + 1 file changed, 10 insertions(+), 8 deletions(-) + +--- a/hw/s390x/virtio-ccw.c ++++ b/hw/s390x/virtio-ccw.c +@@ -1152,9 +1152,10 @@ static inline VirtioCcwDevice *to_virtio + static uint8_t virtio_set_ind_atomic(SubchDev *sch, uint64_t ind_loc, + uint8_t to_be_set) + { +- uint8_t ind_old, ind_new; ++ uint8_t expected, actual; + hwaddr len = 1; +- uint8_t *ind_addr; ++ /* avoid multiple fetches */ ++ uint8_t volatile *ind_addr; + + ind_addr = cpu_physical_memory_map(ind_loc, &len, 1); + if (!ind_addr) { +@@ -1162,13 +1163,14 @@ static uint8_t virtio_set_ind_atomic(Sub + __func__, sch->cssid, sch->ssid, sch->schid); + return -1; + } ++ actual = *ind_addr; + do { +- ind_old = *ind_addr; +- ind_new = ind_old | to_be_set; +- } while (atomic_cmpxchg(ind_addr, ind_old, ind_new) != ind_old); +- cpu_physical_memory_unmap(ind_addr, len, 1, len); ++ expected = actual; ++ actual = atomic_cmpxchg(ind_addr, expected, expected | to_be_set); ++ } while (actual != expected); ++ cpu_physical_memory_unmap((void *)ind_addr, len, 1, len); + +- return ind_old; ++ return actual; + } + + static void virtio_ccw_notify(DeviceState *d, uint16_t vector)