Fix CVE-2020-27675 (rhbz 1891114 1891115)
Signed-off-by: Justin M. Forbes <jforbes@fedoraproject.org>
This commit is contained in:
parent
011aad74d2
commit
82b65923c7
161
0001-xen-events-avoid-removing-an-event-channel-while-han.patch
Normal file
161
0001-xen-events-avoid-removing-an-event-channel-while-han.patch
Normal file
@ -0,0 +1,161 @@
|
|||||||
|
From 073d0552ead5bfc7a3a9c01de590e924f11b5dd2 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Juergen Gross <jgross@suse.com>
|
||||||
|
Date: Mon, 7 Sep 2020 15:47:27 +0200
|
||||||
|
Subject: [PATCH] xen/events: avoid removing an event channel while handling it
|
||||||
|
MIME-Version: 1.0
|
||||||
|
Content-Type: text/plain; charset=UTF-8
|
||||||
|
Content-Transfer-Encoding: 8bit
|
||||||
|
|
||||||
|
Today it can happen that an event channel is being removed from the
|
||||||
|
system while the event handling loop is active. This can lead to a
|
||||||
|
race resulting in crashes or WARN() splats when trying to access the
|
||||||
|
irq_info structure related to the event channel.
|
||||||
|
|
||||||
|
Fix this problem by using a rwlock taken as reader in the event
|
||||||
|
handling loop and as writer when deallocating the irq_info structure.
|
||||||
|
|
||||||
|
As the observed problem was a NULL dereference in evtchn_from_irq()
|
||||||
|
make this function more robust against races by testing the irq_info
|
||||||
|
pointer to be not NULL before dereferencing it.
|
||||||
|
|
||||||
|
And finally make all accesses to evtchn_to_irq[row][col] atomic ones
|
||||||
|
in order to avoid seeing partial updates of an array element in irq
|
||||||
|
handling. Note that irq handling can be entered only for event channels
|
||||||
|
which have been valid before, so any not populated row isn't a problem
|
||||||
|
in this regard, as rows are only ever added and never removed.
|
||||||
|
|
||||||
|
This is XSA-331.
|
||||||
|
|
||||||
|
Cc: stable@vger.kernel.org
|
||||||
|
Reported-by: Marek Marczykowski-Górecki <marmarek@invisiblethingslab.com>
|
||||||
|
Reported-by: Jinoh Kang <luke1337@theori.io>
|
||||||
|
Signed-off-by: Juergen Gross <jgross@suse.com>
|
||||||
|
Reviewed-by: Stefano Stabellini <sstabellini@kernel.org>
|
||||||
|
Reviewed-by: Wei Liu <wl@xen.org>
|
||||||
|
---
|
||||||
|
drivers/xen/events/events_base.c | 41 ++++++++++++++++++++++++++++----
|
||||||
|
1 file changed, 36 insertions(+), 5 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/drivers/xen/events/events_base.c b/drivers/xen/events/events_base.c
|
||||||
|
index 6f02c18fa65c..407741ece084 100644
|
||||||
|
--- a/drivers/xen/events/events_base.c
|
||||||
|
+++ b/drivers/xen/events/events_base.c
|
||||||
|
@@ -33,6 +33,7 @@
|
||||||
|
#include <linux/slab.h>
|
||||||
|
#include <linux/irqnr.h>
|
||||||
|
#include <linux/pci.h>
|
||||||
|
+#include <linux/spinlock.h>
|
||||||
|
|
||||||
|
#ifdef CONFIG_X86
|
||||||
|
#include <asm/desc.h>
|
||||||
|
@@ -71,6 +72,23 @@ const struct evtchn_ops *evtchn_ops;
|
||||||
|
*/
|
||||||
|
static DEFINE_MUTEX(irq_mapping_update_lock);
|
||||||
|
|
||||||
|
+/*
|
||||||
|
+ * Lock protecting event handling loop against removing event channels.
|
||||||
|
+ * Adding of event channels is no issue as the associated IRQ becomes active
|
||||||
|
+ * only after everything is setup (before request_[threaded_]irq() the handler
|
||||||
|
+ * can't be entered for an event, as the event channel will be unmasked only
|
||||||
|
+ * then).
|
||||||
|
+ */
|
||||||
|
+static DEFINE_RWLOCK(evtchn_rwlock);
|
||||||
|
+
|
||||||
|
+/*
|
||||||
|
+ * Lock hierarchy:
|
||||||
|
+ *
|
||||||
|
+ * irq_mapping_update_lock
|
||||||
|
+ * evtchn_rwlock
|
||||||
|
+ * IRQ-desc lock
|
||||||
|
+ */
|
||||||
|
+
|
||||||
|
static LIST_HEAD(xen_irq_list_head);
|
||||||
|
|
||||||
|
/* IRQ <-> VIRQ mapping. */
|
||||||
|
@@ -105,7 +123,7 @@ static void clear_evtchn_to_irq_row(unsigned row)
|
||||||
|
unsigned col;
|
||||||
|
|
||||||
|
for (col = 0; col < EVTCHN_PER_ROW; col++)
|
||||||
|
- evtchn_to_irq[row][col] = -1;
|
||||||
|
+ WRITE_ONCE(evtchn_to_irq[row][col], -1);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void clear_evtchn_to_irq_all(void)
|
||||||
|
@@ -142,7 +160,7 @@ static int set_evtchn_to_irq(evtchn_port_t evtchn, unsigned int irq)
|
||||||
|
clear_evtchn_to_irq_row(row);
|
||||||
|
}
|
||||||
|
|
||||||
|
- evtchn_to_irq[row][col] = irq;
|
||||||
|
+ WRITE_ONCE(evtchn_to_irq[row][col], irq);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
@@ -152,7 +170,7 @@ int get_evtchn_to_irq(evtchn_port_t evtchn)
|
||||||
|
return -1;
|
||||||
|
if (evtchn_to_irq[EVTCHN_ROW(evtchn)] == NULL)
|
||||||
|
return -1;
|
||||||
|
- return evtchn_to_irq[EVTCHN_ROW(evtchn)][EVTCHN_COL(evtchn)];
|
||||||
|
+ return READ_ONCE(evtchn_to_irq[EVTCHN_ROW(evtchn)][EVTCHN_COL(evtchn)]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Get info for IRQ */
|
||||||
|
@@ -261,10 +279,14 @@ static void xen_irq_info_cleanup(struct irq_info *info)
|
||||||
|
*/
|
||||||
|
evtchn_port_t evtchn_from_irq(unsigned irq)
|
||||||
|
{
|
||||||
|
- if (WARN(irq >= nr_irqs, "Invalid irq %d!\n", irq))
|
||||||
|
+ const struct irq_info *info = NULL;
|
||||||
|
+
|
||||||
|
+ if (likely(irq < nr_irqs))
|
||||||
|
+ info = info_for_irq(irq);
|
||||||
|
+ if (!info)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
- return info_for_irq(irq)->evtchn;
|
||||||
|
+ return info->evtchn;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned int irq_from_evtchn(evtchn_port_t evtchn)
|
||||||
|
@@ -440,16 +462,21 @@ static int __must_check xen_allocate_irq_gsi(unsigned gsi)
|
||||||
|
static void xen_free_irq(unsigned irq)
|
||||||
|
{
|
||||||
|
struct irq_info *info = info_for_irq(irq);
|
||||||
|
+ unsigned long flags;
|
||||||
|
|
||||||
|
if (WARN_ON(!info))
|
||||||
|
return;
|
||||||
|
|
||||||
|
+ write_lock_irqsave(&evtchn_rwlock, flags);
|
||||||
|
+
|
||||||
|
list_del(&info->list);
|
||||||
|
|
||||||
|
set_info_for_irq(irq, NULL);
|
||||||
|
|
||||||
|
WARN_ON(info->refcnt > 0);
|
||||||
|
|
||||||
|
+ write_unlock_irqrestore(&evtchn_rwlock, flags);
|
||||||
|
+
|
||||||
|
kfree(info);
|
||||||
|
|
||||||
|
/* Legacy IRQ descriptors are managed by the arch. */
|
||||||
|
@@ -1233,6 +1260,8 @@ static void __xen_evtchn_do_upcall(void)
|
||||||
|
struct vcpu_info *vcpu_info = __this_cpu_read(xen_vcpu);
|
||||||
|
int cpu = smp_processor_id();
|
||||||
|
|
||||||
|
+ read_lock(&evtchn_rwlock);
|
||||||
|
+
|
||||||
|
do {
|
||||||
|
vcpu_info->evtchn_upcall_pending = 0;
|
||||||
|
|
||||||
|
@@ -1243,6 +1272,8 @@ static void __xen_evtchn_do_upcall(void)
|
||||||
|
virt_rmb(); /* Hypervisor can set upcall pending. */
|
||||||
|
|
||||||
|
} while (vcpu_info->evtchn_upcall_pending);
|
||||||
|
+
|
||||||
|
+ read_unlock(&evtchn_rwlock);
|
||||||
|
}
|
||||||
|
|
||||||
|
void xen_evtchn_do_upcall(struct pt_regs *regs)
|
||||||
|
--
|
||||||
|
2.28.0
|
||||||
|
|
@ -902,6 +902,9 @@ Patch130: arm64-dts-allwinner-h5-OrangePi-PC2-Fix-ethernet-node.patch
|
|||||||
# https://patchwork.kernel.org/project/linux-arm-kernel/patch/20201023194902.368239-1-jernej.skrabec@siol.net/
|
# https://patchwork.kernel.org/project/linux-arm-kernel/patch/20201023194902.368239-1-jernej.skrabec@siol.net/
|
||||||
Patch131: arm64-dts-allwinner-h6-Pine-H64-Fix-ethernet-node.patch
|
Patch131: arm64-dts-allwinner-h6-Pine-H64-Fix-ethernet-node.patch
|
||||||
|
|
||||||
|
# CVE-2020-27675 rhbz 1891114 1891115
|
||||||
|
Patch132: 0001-xen-events-avoid-removing-an-event-channel-while-han.patch
|
||||||
|
|
||||||
# END OF PATCH DEFINITIONS
|
# END OF PATCH DEFINITIONS
|
||||||
|
|
||||||
%endif
|
%endif
|
||||||
@ -3017,6 +3020,7 @@ fi
|
|||||||
%changelog
|
%changelog
|
||||||
* Thu Oct 29 07:55:15 CDT 2020 Justin M. Forbes <jforbes@fedoraproject.org> - 5.8.17-300
|
* Thu Oct 29 07:55:15 CDT 2020 Justin M. Forbes <jforbes@fedoraproject.org> - 5.8.17-300
|
||||||
- Linux v5.8.17
|
- Linux v5.8.17
|
||||||
|
- Fix CVE-2020-27675 (rhbz 1891114 1891115)
|
||||||
|
|
||||||
* Wed Oct 28 2020 Peter Robinson <pbrobinson@fedoraproject.org>
|
* Wed Oct 28 2020 Peter Robinson <pbrobinson@fedoraproject.org>
|
||||||
- Fixes for AllWinner wired network issues due to Realtek PHY driver change (rhbz 1889090)
|
- Fixes for AllWinner wired network issues due to Realtek PHY driver change (rhbz 1889090)
|
||||||
|
Loading…
Reference in New Issue
Block a user