Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 29 Mar 2023 07:52:28 GMT
From:      =?utf-8?Q?Roger=20Pau=20Monn=C3=A9?= <royger@FreeBSD.org>
To:        src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-main@FreeBSD.org
Subject:   git: 2b2415bafa0d - main - xen/intr: fix corruption of event channel table
Message-ID:  <202303290752.32T7qSGm051982@gitrepo.freebsd.org>

next in thread | raw e-mail | index | archive | help
The branch main has been updated by royger:

URL: https://cgit.FreeBSD.org/src/commit/?id=2b2415bafa0dda36244f0fedef9f8750b2868dea

commit 2b2415bafa0dda36244f0fedef9f8750b2868dea
Author:     Elliott Mitchell <ehem+freebsd@m5p.com>
AuthorDate: 2021-08-27 23:00:05 +0000
Commit:     Roger Pau Monné <royger@FreeBSD.org>
CommitDate: 2023-03-29 07:51:40 +0000

    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
---
 sys/x86/xen/xen_intr.c | 27 +++++++++++++++------------
 1 file 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;



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?202303290752.32T7qSGm051982>