aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorElliott Mitchell <ehem+freebsd@m5p.com>2021-08-27 23:00:05 +0000
committerRoger Pau Monné <royger@FreeBSD.org>2023-03-29 07:51:40 +0000
commit2b2415bafa0dda36244f0fedef9f8750b2868dea (patch)
tree5049103b28ee3fe44fa2c89454685e5d77de21af
parent0ebf9bb42d7cb94e28a69cfc8efeb17dc9468955 (diff)
downloadsrc-2b2415bafa0dda36244f0fedef9f8750b2868dea.tar.gz
src-2b2415bafa0dda36244f0fedef9f8750b2868dea.zip
xen/intr: fix corruption of event channel table
In xen_intr_release_isrc(), the isrc should only be removed if it is assigned to a valid port. This had been mitigated by using 0 for not having a port, but this is actually corrupting the table. Fix this bug as modifying the code would cause this bug to manifest as kernel memory corruption. Similar issue for the vCPU bitmap masks. The KASSERT() doesn't need lock protection. Reviewed by: royger MFC after: 1 week Differential Revision: https://reviews.freebsd.org/D30743
-rw-r--r--sys/x86/xen/xen_intr.c27
1 files changed, 15 insertions, 12 deletions
diff --git a/sys/x86/xen/xen_intr.c b/sys/x86/xen/xen_intr.c
index ca0f56a8546a..4e16778874b5 100644
--- a/sys/x86/xen/xen_intr.c
+++ b/sys/x86/xen/xen_intr.c
@@ -350,23 +350,26 @@ static int
xen_intr_release_isrc(struct xenisrc *isrc)
{
- mtx_lock(&xen_intr_isrc_lock);
KASSERT(isrc->xi_intsrc.is_handlers == 0,
("Release called, but xenisrc still in use"));
- evtchn_mask_port(isrc->xi_port);
- evtchn_clear_port(isrc->xi_port);
+ mtx_lock(&xen_intr_isrc_lock);
+ if (is_valid_evtchn(isrc->xi_port)) {
+ evtchn_mask_port(isrc->xi_port);
+ evtchn_clear_port(isrc->xi_port);
- /* Rebind port to CPU 0. */
- evtchn_cpu_mask_port(isrc->xi_cpu, isrc->xi_port);
- evtchn_cpu_unmask_port(0, isrc->xi_port);
+ /* Rebind port to CPU 0. */
+ evtchn_cpu_mask_port(isrc->xi_cpu, isrc->xi_port);
+ evtchn_cpu_unmask_port(0, isrc->xi_port);
- if (isrc->xi_close != 0 && is_valid_evtchn(isrc->xi_port)) {
- struct evtchn_close close = { .port = isrc->xi_port };
- if (HYPERVISOR_event_channel_op(EVTCHNOP_close, &close))
- panic("EVTCHNOP_close failed");
- }
+ if (isrc->xi_close != 0) {
+ struct evtchn_close close = { .port = isrc->xi_port };
- xen_intr_port_to_isrc[isrc->xi_port] = NULL;
+ if (HYPERVISOR_event_channel_op(EVTCHNOP_close, &close))
+ panic("EVTCHNOP_close failed");
+ }
+
+ xen_intr_port_to_isrc[isrc->xi_port] = NULL;
+ }
isrc->xi_cpu = 0;
isrc->xi_type = EVTCHN_TYPE_UNBOUND;
isrc->xi_port = 0;