From 9f9f7be82603f30223a85225bf7fffff0ff4dab5 Mon Sep 17 00:00:00 2001 From: yezengruan Date: Sat, 21 May 2022 14:25:26 +0800 Subject: [PATCH] fix CVE-2021-3750 and Check that colo-compare is active (openeuler !290!297) hw/intc/arm_gicv3_dist: Rename 64-bit accessors with 'q' suffix hw/intc/arm_gicv3: Replace mis-used MEMTX_* constants by booleans hw/intc/arm_gicv3: Check for !MEMTX_OK instead of MEMTX_ERROR (CVE-2021-3750) net/colo-compare.c: Check that colo-compare is active --- ...3-Check-for-MEMTX_OK-instead-of-MEMT.patch | 55 ++ ...3-Replace-mis-used-MEMTX_-constants-.patch | 637 ++++++++++++++++++ ...3_dist-Rename-64-bit-accessors-with-.patch | 67 ++ ....c-Check-that-colo-compare-is-active.patch | 129 ++++ qemu.spec | 12 +- 5 files changed, 899 insertions(+), 1 deletion(-) create mode 100644 hw-intc-arm_gicv3-Check-for-MEMTX_OK-instead-of-MEMT.patch create mode 100644 hw-intc-arm_gicv3-Replace-mis-used-MEMTX_-constants-.patch create mode 100644 hw-intc-arm_gicv3_dist-Rename-64-bit-accessors-with-.patch create mode 100644 net-colo-compare.c-Check-that-colo-compare-is-active.patch diff --git a/hw-intc-arm_gicv3-Check-for-MEMTX_OK-instead-of-MEMT.patch b/hw-intc-arm_gicv3-Check-for-MEMTX_OK-instead-of-MEMT.patch new file mode 100644 index 0000000..0bc56ea --- /dev/null +++ b/hw-intc-arm_gicv3-Check-for-MEMTX_OK-instead-of-MEMT.patch @@ -0,0 +1,55 @@ +From 0bf2096f7967af3c28280c72803f25c7c226d218 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= +Date: Wed, 15 Dec 2021 19:24:19 +0100 +Subject: [PATCH 3/4] hw/intc/arm_gicv3: Check for !MEMTX_OK instead of + MEMTX_ERROR +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Quoting Peter Maydell: + + "These MEMTX_* aren't from the memory transaction + API functions; they're just being used by gicd_readl() and + friends as a way to indicate a success/failure so that the + actual MemoryRegionOps read/write fns like gicv3_dist_read() + can log a guest error." + +We are going to introduce more MemTxResult bits, so it is +safer to check for !MEMTX_OK rather than MEMTX_ERROR. + +Reviewed-by: Peter Xu +Reviewed-by: David Hildenbrand +Reviewed-by: Peter Maydell +Reviewed-by: Stefan Hajnoczi +Signed-off-by: Philippe Mathieu-Daudé +Signed-off-by: Peter Maydell +--- + hw/intc/arm_gicv3_redist.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/hw/intc/arm_gicv3_redist.c b/hw/intc/arm_gicv3_redist.c +index 8645220d61..44368e285a 100644 +--- a/hw/intc/arm_gicv3_redist.c ++++ b/hw/intc/arm_gicv3_redist.c +@@ -450,7 +450,7 @@ MemTxResult gicv3_redist_read(void *opaque, hwaddr offset, uint64_t *data, + break; + } + +- if (r == MEMTX_ERROR) { ++ if (r != MEMTX_OK) { + qemu_log_mask(LOG_GUEST_ERROR, + "%s: invalid guest read at offset " TARGET_FMT_plx + "size %u\n", __func__, offset, size); +@@ -507,7 +507,7 @@ MemTxResult gicv3_redist_write(void *opaque, hwaddr offset, uint64_t data, + break; + } + +- if (r == MEMTX_ERROR) { ++ if (r != MEMTX_OK) { + qemu_log_mask(LOG_GUEST_ERROR, + "%s: invalid guest write at offset " TARGET_FMT_plx + "size %u\n", __func__, offset, size); +-- +2.27.0 + diff --git a/hw-intc-arm_gicv3-Replace-mis-used-MEMTX_-constants-.patch b/hw-intc-arm_gicv3-Replace-mis-used-MEMTX_-constants-.patch new file mode 100644 index 0000000..7f353b2 --- /dev/null +++ b/hw-intc-arm_gicv3-Replace-mis-used-MEMTX_-constants-.patch @@ -0,0 +1,637 @@ +From ecf1c65fd15dcb0d57cb8e029db185c7adaad3b9 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= +Date: Thu, 26 Aug 2021 20:07:04 +0200 +Subject: [PATCH 2/4] hw/intc/arm_gicv3: Replace mis-used MEMTX_* constants by + booleans +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Quoting Peter Maydell: + + These MEMTX_* aren't from the memory transaction API functions; + they're just being used by gicd_readl() and friends as a way to + indicate a success/failure so that the actual MemoryRegionOps + read/write fns like gicv3_dist_read() can log a guest error. + Arguably this is a bit of a misuse of the MEMTX_* constants and + perhaps we should have gicd_readl etc return a bool instead. + +Follow his suggestion and replace the MEMTX_* constants by +boolean values, simplifying a bit the gicv3_dist_read() / +gicv3_dist_write() handlers. + +Suggested-by: Peter Maydell +Signed-off-by: Philippe Mathieu-Daudé +Message-id: 20210826180704.2131949-3-philmd@redhat.com +Signed-off-by: Peter Maydell +--- + hw/intc/arm_gicv3_dist.c | 201 +++++++++++++++++++++------------------ + 1 file changed, 106 insertions(+), 95 deletions(-) + +diff --git a/hw/intc/arm_gicv3_dist.c b/hw/intc/arm_gicv3_dist.c +index 7e9b393d9a..5beb7c4235 100644 +--- a/hw/intc/arm_gicv3_dist.c ++++ b/hw/intc/arm_gicv3_dist.c +@@ -262,8 +262,21 @@ static void gicd_write_irouter(GICv3State *s, MemTxAttrs attrs, int irq, + gicv3_update(s, irq, 1); + } + +-static MemTxResult gicd_readb(GICv3State *s, hwaddr offset, +- uint64_t *data, MemTxAttrs attrs) ++/** ++ * gicd_readb ++ * gicd_readw ++ * gicd_readl ++ * gicd_readq ++ * gicd_writeb ++ * gicd_writew ++ * gicd_writel ++ * gicd_writeq ++ * ++ * Return %true if the operation succeeded, %false otherwise. ++ */ ++ ++static bool gicd_readb(GICv3State *s, hwaddr offset, ++ uint64_t *data, MemTxAttrs attrs) + { + /* Most GICv3 distributor registers do not support byte accesses. */ + switch (offset) { +@@ -273,17 +286,17 @@ static MemTxResult gicd_readb(GICv3State *s, hwaddr offset, + /* This GIC implementation always has affinity routing enabled, + * so these registers are all RAZ/WI. + */ +- return MEMTX_OK; ++ return true; + case GICD_IPRIORITYR ... GICD_IPRIORITYR + 0x3ff: + *data = gicd_read_ipriorityr(s, attrs, offset - GICD_IPRIORITYR); +- return MEMTX_OK; ++ return true; + default: +- return MEMTX_ERROR; ++ return false; + } + } + +-static MemTxResult gicd_writeb(GICv3State *s, hwaddr offset, +- uint64_t value, MemTxAttrs attrs) ++static bool gicd_writeb(GICv3State *s, hwaddr offset, ++ uint64_t value, MemTxAttrs attrs) + { + /* Most GICv3 distributor registers do not support byte accesses. */ + switch (offset) { +@@ -293,25 +306,25 @@ static MemTxResult gicd_writeb(GICv3State *s, hwaddr offset, + /* This GIC implementation always has affinity routing enabled, + * so these registers are all RAZ/WI. + */ +- return MEMTX_OK; ++ return true; + case GICD_IPRIORITYR ... GICD_IPRIORITYR + 0x3ff: + { + int irq = offset - GICD_IPRIORITYR; + + if (irq < GIC_INTERNAL || irq >= s->num_irq) { +- return MEMTX_OK; ++ return true; + } + gicd_write_ipriorityr(s, attrs, irq, value); + gicv3_update(s, irq, 1); +- return MEMTX_OK; ++ return true; + } + default: +- return MEMTX_ERROR; ++ return false; + } + } + +-static MemTxResult gicd_readw(GICv3State *s, hwaddr offset, +- uint64_t *data, MemTxAttrs attrs) ++static bool gicd_readw(GICv3State *s, hwaddr offset, ++ uint64_t *data, MemTxAttrs attrs) + { + /* Only GICD_SETSPI_NSR, GICD_CLRSPI_NSR, GICD_SETSPI_SR and GICD_SETSPI_NSR + * support 16 bit accesses, and those registers are all part of the +@@ -319,11 +332,11 @@ static MemTxResult gicd_readw(GICv3State *s, hwaddr offset, + * implement (ie for us GICD_TYPER.MBIS == 0), so for us they are + * reserved. + */ +- return MEMTX_ERROR; ++ return false; + } + +-static MemTxResult gicd_writew(GICv3State *s, hwaddr offset, +- uint64_t value, MemTxAttrs attrs) ++static bool gicd_writew(GICv3State *s, hwaddr offset, ++ uint64_t value, MemTxAttrs attrs) + { + /* Only GICD_SETSPI_NSR, GICD_CLRSPI_NSR, GICD_SETSPI_SR and GICD_SETSPI_NSR + * support 16 bit accesses, and those registers are all part of the +@@ -331,11 +344,11 @@ static MemTxResult gicd_writew(GICv3State *s, hwaddr offset, + * implement (ie for us GICD_TYPER.MBIS == 0), so for us they are + * reserved. + */ +- return MEMTX_ERROR; ++ return false; + } + +-static MemTxResult gicd_readl(GICv3State *s, hwaddr offset, +- uint64_t *data, MemTxAttrs attrs) ++static bool gicd_readl(GICv3State *s, hwaddr offset, ++ uint64_t *data, MemTxAttrs attrs) + { + /* Almost all GICv3 distributor registers are 32-bit. + * Note that WO registers must return an UNKNOWN value on reads, +@@ -363,7 +376,7 @@ static MemTxResult gicd_readl(GICv3State *s, hwaddr offset, + } else { + *data = s->gicd_ctlr; + } +- return MEMTX_OK; ++ return true; + case GICD_TYPER: + { + /* For this implementation: +@@ -387,61 +400,61 @@ static MemTxResult gicd_readl(GICv3State *s, hwaddr offset, + + *data = (1 << 25) | (1 << 24) | (sec_extn << 10) | + (0xf << 19) | itlinesnumber; +- return MEMTX_OK; ++ return true; + } + case GICD_IIDR: + /* We claim to be an ARM r0p0 with a zero ProductID. + * This is the same as an r0p0 GIC-500. + */ + *data = gicv3_iidr(); +- return MEMTX_OK; ++ return true; + case GICD_STATUSR: + /* RAZ/WI for us (this is an optional register and our implementation + * does not track RO/WO/reserved violations to report them to the guest) + */ + *data = 0; +- return MEMTX_OK; ++ return true; + case GICD_IGROUPR ... GICD_IGROUPR + 0x7f: + { + int irq; + + if (!attrs.secure && !(s->gicd_ctlr & GICD_CTLR_DS)) { + *data = 0; +- return MEMTX_OK; ++ return true; + } + /* RAZ/WI for SGIs, PPIs, unimplemented irqs */ + irq = (offset - GICD_IGROUPR) * 8; + if (irq < GIC_INTERNAL || irq >= s->num_irq) { + *data = 0; +- return MEMTX_OK; ++ return true; + } + *data = *gic_bmp_ptr32(s->group, irq); +- return MEMTX_OK; ++ return true; + } + case GICD_ISENABLER ... GICD_ISENABLER + 0x7f: + *data = gicd_read_bitmap_reg(s, attrs, s->enabled, NULL, + offset - GICD_ISENABLER); +- return MEMTX_OK; ++ return true; + case GICD_ICENABLER ... GICD_ICENABLER + 0x7f: + *data = gicd_read_bitmap_reg(s, attrs, s->enabled, NULL, + offset - GICD_ICENABLER); +- return MEMTX_OK; ++ return true; + case GICD_ISPENDR ... GICD_ISPENDR + 0x7f: + *data = gicd_read_bitmap_reg(s, attrs, s->pending, mask_nsacr_ge1, + offset - GICD_ISPENDR); +- return MEMTX_OK; ++ return true; + case GICD_ICPENDR ... GICD_ICPENDR + 0x7f: + *data = gicd_read_bitmap_reg(s, attrs, s->pending, mask_nsacr_ge2, + offset - GICD_ICPENDR); +- return MEMTX_OK; ++ return true; + case GICD_ISACTIVER ... GICD_ISACTIVER + 0x7f: + *data = gicd_read_bitmap_reg(s, attrs, s->active, mask_nsacr_ge2, + offset - GICD_ISACTIVER); +- return MEMTX_OK; ++ return true; + case GICD_ICACTIVER ... GICD_ICACTIVER + 0x7f: + *data = gicd_read_bitmap_reg(s, attrs, s->active, mask_nsacr_ge2, + offset - GICD_ICACTIVER); +- return MEMTX_OK; ++ return true; + case GICD_IPRIORITYR ... GICD_IPRIORITYR + 0x3ff: + { + int i, irq = offset - GICD_IPRIORITYR; +@@ -452,12 +465,12 @@ static MemTxResult gicd_readl(GICv3State *s, hwaddr offset, + value |= gicd_read_ipriorityr(s, attrs, i); + } + *data = value; +- return MEMTX_OK; ++ return true; + } + case GICD_ITARGETSR ... GICD_ITARGETSR + 0x3ff: + /* RAZ/WI since affinity routing is always enabled */ + *data = 0; +- return MEMTX_OK; ++ return true; + case GICD_ICFGR ... GICD_ICFGR + 0xff: + { + /* Here only the even bits are used; odd bits are RES0 */ +@@ -466,7 +479,7 @@ static MemTxResult gicd_readl(GICv3State *s, hwaddr offset, + + if (irq < GIC_INTERNAL || irq >= s->num_irq) { + *data = 0; +- return MEMTX_OK; ++ return true; + } + + /* Since our edge_trigger bitmap is one bit per irq, we only need +@@ -478,7 +491,7 @@ static MemTxResult gicd_readl(GICv3State *s, hwaddr offset, + value = extract32(value, (irq & 0x1f) ? 16 : 0, 16); + value = half_shuffle32(value) << 1; + *data = value; +- return MEMTX_OK; ++ return true; + } + case GICD_IGRPMODR ... GICD_IGRPMODR + 0xff: + { +@@ -489,16 +502,16 @@ static MemTxResult gicd_readl(GICv3State *s, hwaddr offset, + * security enabled and this is an NS access + */ + *data = 0; +- return MEMTX_OK; ++ return true; + } + /* RAZ/WI for SGIs, PPIs, unimplemented irqs */ + irq = (offset - GICD_IGRPMODR) * 8; + if (irq < GIC_INTERNAL || irq >= s->num_irq) { + *data = 0; +- return MEMTX_OK; ++ return true; + } + *data = *gic_bmp_ptr32(s->grpmod, irq); +- return MEMTX_OK; ++ return true; + } + case GICD_NSACR ... GICD_NSACR + 0xff: + { +@@ -507,7 +520,7 @@ static MemTxResult gicd_readl(GICv3State *s, hwaddr offset, + + if (irq < GIC_INTERNAL || irq >= s->num_irq) { + *data = 0; +- return MEMTX_OK; ++ return true; + } + + if ((s->gicd_ctlr & GICD_CTLR_DS) || !attrs.secure) { +@@ -515,17 +528,17 @@ static MemTxResult gicd_readl(GICv3State *s, hwaddr offset, + * security enabled and this is an NS access + */ + *data = 0; +- return MEMTX_OK; ++ return true; + } + + *data = s->gicd_nsacr[irq / 16]; +- return MEMTX_OK; ++ return true; + } + case GICD_CPENDSGIR ... GICD_CPENDSGIR + 0xf: + case GICD_SPENDSGIR ... GICD_SPENDSGIR + 0xf: + /* RAZ/WI since affinity routing is always enabled */ + *data = 0; +- return MEMTX_OK; ++ return true; + case GICD_IROUTER ... GICD_IROUTER + 0x1fdf: + { + uint64_t r; +@@ -537,26 +550,26 @@ static MemTxResult gicd_readl(GICv3State *s, hwaddr offset, + } else { + *data = (uint32_t)r; + } +- return MEMTX_OK; ++ return true; + } + case GICD_IDREGS ... GICD_IDREGS + 0x2f: + /* ID registers */ + *data = gicv3_idreg(offset - GICD_IDREGS); +- return MEMTX_OK; ++ return true; + case GICD_SGIR: + /* WO registers, return unknown value */ + qemu_log_mask(LOG_GUEST_ERROR, + "%s: invalid guest read from WO register at offset " + TARGET_FMT_plx "\n", __func__, offset); + *data = 0; +- return MEMTX_OK; ++ return true; + default: +- return MEMTX_ERROR; ++ return false; + } + } + +-static MemTxResult gicd_writel(GICv3State *s, hwaddr offset, +- uint64_t value, MemTxAttrs attrs) ++static bool gicd_writel(GICv3State *s, hwaddr offset, ++ uint64_t value, MemTxAttrs attrs) + { + /* Almost all GICv3 distributor registers are 32-bit. Note that + * RO registers must ignore writes, not abort. +@@ -600,68 +613,68 @@ static MemTxResult gicd_writel(GICv3State *s, hwaddr offset, + s->gicd_ctlr &= ~(GICD_CTLR_EN_GRP1S | GICD_CTLR_ARE_NS); + } + gicv3_full_update(s); +- return MEMTX_OK; ++ return true; + } + case GICD_STATUSR: + /* RAZ/WI for our implementation */ +- return MEMTX_OK; ++ return true; + case GICD_IGROUPR ... GICD_IGROUPR + 0x7f: + { + int irq; + + if (!attrs.secure && !(s->gicd_ctlr & GICD_CTLR_DS)) { +- return MEMTX_OK; ++ return true; + } + /* RAZ/WI for SGIs, PPIs, unimplemented irqs */ + irq = (offset - GICD_IGROUPR) * 8; + if (irq < GIC_INTERNAL || irq >= s->num_irq) { +- return MEMTX_OK; ++ return true; + } + *gic_bmp_ptr32(s->group, irq) = value; + gicv3_update(s, irq, 32); +- return MEMTX_OK; ++ return true; + } + case GICD_ISENABLER ... GICD_ISENABLER + 0x7f: + gicd_write_set_bitmap_reg(s, attrs, s->enabled, NULL, + offset - GICD_ISENABLER, value); +- return MEMTX_OK; ++ return true; + case GICD_ICENABLER ... GICD_ICENABLER + 0x7f: + gicd_write_clear_bitmap_reg(s, attrs, s->enabled, NULL, + offset - GICD_ICENABLER, value); +- return MEMTX_OK; ++ return true; + case GICD_ISPENDR ... GICD_ISPENDR + 0x7f: + gicd_write_set_bitmap_reg(s, attrs, s->pending, mask_nsacr_ge1, + offset - GICD_ISPENDR, value); +- return MEMTX_OK; ++ return true; + case GICD_ICPENDR ... GICD_ICPENDR + 0x7f: + gicd_write_clear_bitmap_reg(s, attrs, s->pending, mask_nsacr_ge2, + offset - GICD_ICPENDR, value); +- return MEMTX_OK; ++ return true; + case GICD_ISACTIVER ... GICD_ISACTIVER + 0x7f: + gicd_write_set_bitmap_reg(s, attrs, s->active, NULL, + offset - GICD_ISACTIVER, value); +- return MEMTX_OK; ++ return true; + case GICD_ICACTIVER ... GICD_ICACTIVER + 0x7f: + gicd_write_clear_bitmap_reg(s, attrs, s->active, NULL, + offset - GICD_ICACTIVER, value); +- return MEMTX_OK; ++ return true; + case GICD_IPRIORITYR ... GICD_IPRIORITYR + 0x3ff: + { + int i, irq = offset - GICD_IPRIORITYR; + + if (irq < GIC_INTERNAL || irq + 3 >= s->num_irq) { +- return MEMTX_OK; ++ return true; + } + + for (i = irq; i < irq + 4; i++, value >>= 8) { + gicd_write_ipriorityr(s, attrs, i, value); + } + gicv3_update(s, irq, 4); +- return MEMTX_OK; ++ return true; + } + case GICD_ITARGETSR ... GICD_ITARGETSR + 0x3ff: + /* RAZ/WI since affinity routing is always enabled */ +- return MEMTX_OK; ++ return true; + case GICD_ICFGR ... GICD_ICFGR + 0xff: + { + /* Here only the odd bits are used; even bits are RES0 */ +@@ -669,7 +682,7 @@ static MemTxResult gicd_writel(GICv3State *s, hwaddr offset, + uint32_t mask, oldval; + + if (irq < GIC_INTERNAL || irq >= s->num_irq) { +- return MEMTX_OK; ++ return true; + } + + /* Since our edge_trigger bitmap is one bit per irq, our input +@@ -687,7 +700,7 @@ static MemTxResult gicd_writel(GICv3State *s, hwaddr offset, + oldval = *gic_bmp_ptr32(s->edge_trigger, (irq & ~0x1f)); + value = (oldval & ~mask) | (value & mask); + *gic_bmp_ptr32(s->edge_trigger, irq & ~0x1f) = value; +- return MEMTX_OK; ++ return true; + } + case GICD_IGRPMODR ... GICD_IGRPMODR + 0xff: + { +@@ -697,16 +710,16 @@ static MemTxResult gicd_writel(GICv3State *s, hwaddr offset, + /* RAZ/WI if security disabled, or if + * security enabled and this is an NS access + */ +- return MEMTX_OK; ++ return true; + } + /* RAZ/WI for SGIs, PPIs, unimplemented irqs */ + irq = (offset - GICD_IGRPMODR) * 8; + if (irq < GIC_INTERNAL || irq >= s->num_irq) { +- return MEMTX_OK; ++ return true; + } + *gic_bmp_ptr32(s->grpmod, irq) = value; + gicv3_update(s, irq, 32); +- return MEMTX_OK; ++ return true; + } + case GICD_NSACR ... GICD_NSACR + 0xff: + { +@@ -714,41 +727,41 @@ static MemTxResult gicd_writel(GICv3State *s, hwaddr offset, + int irq = (offset - GICD_NSACR) * 4; + + if (irq < GIC_INTERNAL || irq >= s->num_irq) { +- return MEMTX_OK; ++ return true; + } + + if ((s->gicd_ctlr & GICD_CTLR_DS) || !attrs.secure) { + /* RAZ/WI if security disabled, or if + * security enabled and this is an NS access + */ +- return MEMTX_OK; ++ return true; + } + + s->gicd_nsacr[irq / 16] = value; + /* No update required as this only affects access permission checks */ +- return MEMTX_OK; ++ return true; + } + case GICD_SGIR: + /* RES0 if affinity routing is enabled */ +- return MEMTX_OK; ++ return true; + case GICD_CPENDSGIR ... GICD_CPENDSGIR + 0xf: + case GICD_SPENDSGIR ... GICD_SPENDSGIR + 0xf: + /* RAZ/WI since affinity routing is always enabled */ +- return MEMTX_OK; ++ return true; + case GICD_IROUTER ... GICD_IROUTER + 0x1fdf: + { + uint64_t r; + int irq = (offset - GICD_IROUTER) / 8; + + if (irq < GIC_INTERNAL || irq >= s->num_irq) { +- return MEMTX_OK; ++ return true; + } + + /* Write half of the 64-bit register */ + r = gicd_read_irouter(s, attrs, irq); + r = deposit64(r, (offset & 7) ? 32 : 0, 32, value); + gicd_write_irouter(s, attrs, irq, r); +- return MEMTX_OK; ++ return true; + } + case GICD_IDREGS ... GICD_IDREGS + 0x2f: + case GICD_TYPER: +@@ -757,14 +770,14 @@ static MemTxResult gicd_writel(GICv3State *s, hwaddr offset, + qemu_log_mask(LOG_GUEST_ERROR, + "%s: invalid guest write to RO register at offset " + TARGET_FMT_plx "\n", __func__, offset); +- return MEMTX_OK; ++ return true; + default: +- return MEMTX_ERROR; ++ return false; + } + } + +-static MemTxResult gicd_writeq(GICv3State *s, hwaddr offset, +- uint64_t value, MemTxAttrs attrs) ++static bool gicd_writeq(GICv3State *s, hwaddr offset, ++ uint64_t value, MemTxAttrs attrs) + { + /* Our only 64-bit registers are GICD_IROUTER */ + int irq; +@@ -773,14 +786,14 @@ static MemTxResult gicd_writeq(GICv3State *s, hwaddr offset, + case GICD_IROUTER ... GICD_IROUTER + 0x1fdf: + irq = (offset - GICD_IROUTER) / 8; + gicd_write_irouter(s, attrs, irq, value); +- return MEMTX_OK; ++ return true; + default: +- return MEMTX_ERROR; ++ return false; + } + } + +-static MemTxResult gicd_readq(GICv3State *s, hwaddr offset, +- uint64_t *data, MemTxAttrs attrs) ++static bool gicd_readq(GICv3State *s, hwaddr offset, ++ uint64_t *data, MemTxAttrs attrs) + { + /* Our only 64-bit registers are GICD_IROUTER */ + int irq; +@@ -789,9 +802,9 @@ static MemTxResult gicd_readq(GICv3State *s, hwaddr offset, + case GICD_IROUTER ... GICD_IROUTER + 0x1fdf: + irq = (offset - GICD_IROUTER) / 8; + *data = gicd_read_irouter(s, attrs, irq); +- return MEMTX_OK; ++ return true; + default: +- return MEMTX_ERROR; ++ return false; + } + } + +@@ -799,7 +812,7 @@ MemTxResult gicv3_dist_read(void *opaque, hwaddr offset, uint64_t *data, + unsigned size, MemTxAttrs attrs) + { + GICv3State *s = (GICv3State *)opaque; +- MemTxResult r; ++ bool r; + + switch (size) { + case 1: +@@ -815,11 +828,11 @@ MemTxResult gicv3_dist_read(void *opaque, hwaddr offset, uint64_t *data, + r = gicd_readq(s, offset, data, attrs); + break; + default: +- r = MEMTX_ERROR; ++ r = false; + break; + } + +- if (r == MEMTX_ERROR) { ++ if (!r) { + qemu_log_mask(LOG_GUEST_ERROR, + "%s: invalid guest read at offset " TARGET_FMT_plx + "size %u\n", __func__, offset, size); +@@ -829,19 +842,18 @@ MemTxResult gicv3_dist_read(void *opaque, hwaddr offset, uint64_t *data, + * trigger the guest-error logging but don't return it to + * the caller, or we'll cause a spurious guest data abort. + */ +- r = MEMTX_OK; + *data = 0; + } else { + trace_gicv3_dist_read(offset, *data, size, attrs.secure); + } +- return r; ++ return MEMTX_OK; + } + + MemTxResult gicv3_dist_write(void *opaque, hwaddr offset, uint64_t data, + unsigned size, MemTxAttrs attrs) + { + GICv3State *s = (GICv3State *)opaque; +- MemTxResult r; ++ bool r; + + switch (size) { + case 1: +@@ -857,11 +869,11 @@ MemTxResult gicv3_dist_write(void *opaque, hwaddr offset, uint64_t data, + r = gicd_writeq(s, offset, data, attrs); + break; + default: +- r = MEMTX_ERROR; ++ r = false; + break; + } + +- if (r == MEMTX_ERROR) { ++ if (!r) { + qemu_log_mask(LOG_GUEST_ERROR, + "%s: invalid guest write at offset " TARGET_FMT_plx + "size %u\n", __func__, offset, size); +@@ -871,11 +883,10 @@ MemTxResult gicv3_dist_write(void *opaque, hwaddr offset, uint64_t data, + * trigger the guest-error logging but don't return it to + * the caller, or we'll cause a spurious guest data abort. + */ +- r = MEMTX_OK; + } else { + trace_gicv3_dist_write(offset, data, size, attrs.secure); + } +- return r; ++ return MEMTX_OK; + } + + void gicv3_dist_set_irq(GICv3State *s, int irq, int level) +-- +2.27.0 + diff --git a/hw-intc-arm_gicv3_dist-Rename-64-bit-accessors-with-.patch b/hw-intc-arm_gicv3_dist-Rename-64-bit-accessors-with-.patch new file mode 100644 index 0000000..2f1b83c --- /dev/null +++ b/hw-intc-arm_gicv3_dist-Rename-64-bit-accessors-with-.patch @@ -0,0 +1,67 @@ +From d8b202275adace1bfcce4fc735f5b05642a08406 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= +Date: Thu, 26 Aug 2021 20:07:03 +0200 +Subject: [PATCH 1/4] hw/intc/arm_gicv3_dist: Rename 64-bit accessors with 'q' + suffix +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +QEMU load/store API (docs/devel/loads-stores.rst) uses the 'q' +suffix for 64-bit accesses. Rename the current 'll' suffix to +have the GIC dist accessors better match the rest of the codebase. + +Signed-off-by: Philippe Mathieu-Daudé +Message-id: 20210826180704.2131949-2-philmd@redhat.com +Signed-off-by: Peter Maydell +--- + hw/intc/arm_gicv3_dist.c | 12 ++++++------ + 1 file changed, 6 insertions(+), 6 deletions(-) + +diff --git a/hw/intc/arm_gicv3_dist.c b/hw/intc/arm_gicv3_dist.c +index b65f56f903..7e9b393d9a 100644 +--- a/hw/intc/arm_gicv3_dist.c ++++ b/hw/intc/arm_gicv3_dist.c +@@ -763,8 +763,8 @@ static MemTxResult gicd_writel(GICv3State *s, hwaddr offset, + } + } + +-static MemTxResult gicd_writell(GICv3State *s, hwaddr offset, +- uint64_t value, MemTxAttrs attrs) ++static MemTxResult gicd_writeq(GICv3State *s, hwaddr offset, ++ uint64_t value, MemTxAttrs attrs) + { + /* Our only 64-bit registers are GICD_IROUTER */ + int irq; +@@ -779,8 +779,8 @@ static MemTxResult gicd_writell(GICv3State *s, hwaddr offset, + } + } + +-static MemTxResult gicd_readll(GICv3State *s, hwaddr offset, +- uint64_t *data, MemTxAttrs attrs) ++static MemTxResult gicd_readq(GICv3State *s, hwaddr offset, ++ uint64_t *data, MemTxAttrs attrs) + { + /* Our only 64-bit registers are GICD_IROUTER */ + int irq; +@@ -812,7 +812,7 @@ MemTxResult gicv3_dist_read(void *opaque, hwaddr offset, uint64_t *data, + r = gicd_readl(s, offset, data, attrs); + break; + case 8: +- r = gicd_readll(s, offset, data, attrs); ++ r = gicd_readq(s, offset, data, attrs); + break; + default: + r = MEMTX_ERROR; +@@ -854,7 +854,7 @@ MemTxResult gicv3_dist_write(void *opaque, hwaddr offset, uint64_t data, + r = gicd_writel(s, offset, data, attrs); + break; + case 8: +- r = gicd_writell(s, offset, data, attrs); ++ r = gicd_writeq(s, offset, data, attrs); + break; + default: + r = MEMTX_ERROR; +-- +2.27.0 + diff --git a/net-colo-compare.c-Check-that-colo-compare-is-active.patch b/net-colo-compare.c-Check-that-colo-compare-is-active.patch new file mode 100644 index 0000000..5fd4652 --- /dev/null +++ b/net-colo-compare.c-Check-that-colo-compare-is-active.patch @@ -0,0 +1,129 @@ +From 5fa5c68cc2dc4c2dad6272670e84767d7830eb1e Mon Sep 17 00:00:00 2001 +From: Lukas Straub +Date: Fri, 22 May 2020 15:53:55 +0800 +Subject: [PATCH 4/4] net/colo-compare.c: Check that colo-compare is active + +If the colo-compare object is removed before failover and a +checkpoint happens, qemu crashes because it tries to lock +the destroyed event_mtx in colo_notify_compares_event. + +Fix this by checking if everything is initialized by +introducing a new variable colo_compare_active which +is protected by a new mutex colo_compare_mutex. The new mutex +also protects against concurrent access of the net_compares +list and makes sure that colo_notify_compares_event isn't +active while we destroy event_mtx and event_complete_cond. + +With this it also is again possible to use colo without +colo-compare (periodic mode) and to use multiple colo-compare +for multiple network interfaces. + +Signed-off-by: Lukas Straub +Tested-by: Lukas Straub +Reviewed-by: Zhang Chen +Signed-off-by: Zhang Chen +Signed-off-by: Jason Wang +--- + net/colo-compare.c | 35 +++++++++++++++++++++++++++++------ + 1 file changed, 29 insertions(+), 6 deletions(-) + +diff --git a/net/colo-compare.c b/net/colo-compare.c +index 7ee17f2cf8..ca07d3016b 100644 +--- a/net/colo-compare.c ++++ b/net/colo-compare.c +@@ -51,6 +51,8 @@ static NotifierList colo_compare_notifiers = + /* TODO: Should be configurable */ + #define REGULAR_PACKET_CHECK_MS 3000 + ++static QemuMutex colo_compare_mutex; ++static bool colo_compare_active; + static QemuMutex event_mtx; + static QemuCond event_complete_cond; + static int event_unhandled_count; +@@ -829,6 +831,12 @@ static void check_old_packet_regular(void *opaque) + void colo_notify_compares_event(void *opaque, int event, Error **errp) + { + CompareState *s; ++ qemu_mutex_lock(&colo_compare_mutex); ++ ++ if (!colo_compare_active) { ++ qemu_mutex_unlock(&colo_compare_mutex); ++ return; ++ } + + qemu_mutex_lock(&event_mtx); + QTAILQ_FOREACH(s, &net_compares, next) { +@@ -842,6 +850,7 @@ void colo_notify_compares_event(void *opaque, int event, Error **errp) + } + + qemu_mutex_unlock(&event_mtx); ++ qemu_mutex_unlock(&colo_compare_mutex); + } + + static void colo_compare_timer_init(CompareState *s) +@@ -1119,13 +1128,17 @@ static void colo_compare_complete(UserCreatable *uc, Error **errp) + s->vnet_hdr); + } + ++ qemu_mutex_lock(&colo_compare_mutex); ++ if (!colo_compare_active) { ++ qemu_mutex_init(&event_mtx); ++ qemu_cond_init(&event_complete_cond); ++ colo_compare_active = true; ++ } + QTAILQ_INSERT_TAIL(&net_compares, s, next); ++ qemu_mutex_unlock(&colo_compare_mutex); + + g_queue_init(&s->conn_list); + +- qemu_mutex_init(&event_mtx); +- qemu_cond_init(&event_complete_cond); +- + s->connection_track_table = g_hash_table_new_full(connection_key_hash, + connection_key_equal, + g_free, +@@ -1208,12 +1221,19 @@ static void colo_compare_finalize(Object *obj) + + qemu_bh_delete(s->event_bh); + ++ qemu_mutex_lock(&colo_compare_mutex); + QTAILQ_FOREACH(tmp, &net_compares, next) { + if (tmp == s) { + QTAILQ_REMOVE(&net_compares, s, next); + break; + } + } ++ if (QTAILQ_EMPTY(&net_compares)) { ++ colo_compare_active = false; ++ qemu_mutex_destroy(&event_mtx); ++ qemu_cond_destroy(&event_complete_cond); ++ } ++ qemu_mutex_unlock(&colo_compare_mutex); + + /* Release all unhandled packets after compare thead exited */ + g_queue_foreach(&s->conn_list, colo_flush_packets, s); +@@ -1228,15 +1248,18 @@ static void colo_compare_finalize(Object *obj) + object_unref(OBJECT(s->iothread)); + } + +- qemu_mutex_destroy(&event_mtx); +- qemu_cond_destroy(&event_complete_cond); +- + g_free(s->pri_indev); + g_free(s->sec_indev); + g_free(s->outdev); + g_free(s->notify_dev); + } + ++static void __attribute__((__constructor__)) colo_compare_init_globals(void) ++{ ++ colo_compare_active = false; ++ qemu_mutex_init(&colo_compare_mutex); ++} ++ + static const TypeInfo colo_compare_info = { + .name = TYPE_COLO_COMPARE, + .parent = TYPE_OBJECT, +-- +2.27.0 + diff --git a/qemu.spec b/qemu.spec index eaaeb70..e5c7198 100644 --- a/qemu.spec +++ b/qemu.spec @@ -1,6 +1,6 @@ Name: qemu Version: 4.1.0 -Release: 67 +Release: 68 Epoch: 2 Summary: QEMU is a generic and open source machine emulator and virtualizer License: GPLv2 and BSD and MIT and CC-BY-SA-4.0 @@ -355,6 +355,10 @@ Patch0342: hw-block-fdc-Kludge-missing-floppy-drive-to-fix-CVE-.patch Patch0343: tests-fdc-test-Add-a-regression-test-for-CVE-2021-20.patch Patch0344: display-qxl-render-fix-race-condition-in-qxl_cursor-.patch Patch0345: ui-cursor-fix-integer-overflow-in-cursor_alloc-CVE-2.patch +Patch0346: hw-intc-arm_gicv3_dist-Rename-64-bit-accessors-with-.patch +Patch0347: hw-intc-arm_gicv3-Replace-mis-used-MEMTX_-constants-.patch +Patch0348: hw-intc-arm_gicv3-Check-for-MEMTX_OK-instead-of-MEMT.patch +Patch0349: net-colo-compare.c-Check-that-colo-compare-is-active.patch BuildRequires: flex BuildRequires: bison @@ -751,6 +755,12 @@ getent passwd qemu >/dev/null || \ %endif %changelog +* Sat May 21 2022 yezengruan +- hw/intc/arm_gicv3_dist: Rename 64-bit accessors with 'q' suffix +- hw/intc/arm_gicv3: Replace mis-used MEMTX_* constants by booleans +- hw/intc/arm_gicv3: Check for !MEMTX_OK instead of MEMTX_ERROR (CVE-2021-3750) +- net/colo-compare.c: Check that colo-compare is active + * Tue May 10 2022 yezengruan - hw/block/fdc: Extract blk_create_empty_drive() - hw/block/fdc: Kludge missing floppy drive to fix CVE-2021-20196 -- Gitee