aboutsummaryrefslogtreecommitdiff
path: root/hw/i386
diff options
context:
space:
mode:
authorDavid Woodhouse <dwmw@amazon.co.uk>2023-07-25 12:05:00 +0200
committerPhilippe Mathieu-Daudé <philmd@linaro.org>2023-08-01 23:52:23 +0200
commit75a87af9b228ca7d14902a9390fe5e83c4898eb0 (patch)
tree9c32705683936eb76605928a8b1e7121a3cf4605 /hw/i386
parent19c417ec87a446ffd1a13eeec23226fe30f31b7e (diff)
downloadqemu-75a87af9b228ca7d14902a9390fe5e83c4898eb0.zip
qemu-75a87af9b228ca7d14902a9390fe5e83c4898eb0.tar.gz
qemu-75a87af9b228ca7d14902a9390fe5e83c4898eb0.tar.bz2
hw/xen: prevent guest from binding loopback event channel to itself
Fuzzing showed that a guest could bind an interdomain port to itself, by guessing the next port to be allocated and putting that as the 'remote' port number. By chance, that works because the newly-allocated port has type EVTCHNSTAT_unbound. It shouldn't. Signed-off-by: David Woodhouse <dwmw@amazon.co.uk> Reviewed-by: Paul Durrant <paul@xen.org> Message-Id: <20230801175747.145906-4-dwmw2@infradead.org> Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org>
Diffstat (limited to 'hw/i386')
-rw-r--r--hw/i386/kvm/xen_evtchn.c11
1 files changed, 9 insertions, 2 deletions
diff --git a/hw/i386/kvm/xen_evtchn.c b/hw/i386/kvm/xen_evtchn.c
index 0e9c108..a731738 100644
--- a/hw/i386/kvm/xen_evtchn.c
+++ b/hw/i386/kvm/xen_evtchn.c
@@ -1408,8 +1408,15 @@ int xen_evtchn_bind_interdomain_op(struct evtchn_bind_interdomain *interdomain)
XenEvtchnPort *rp = &s->port_table[interdomain->remote_port];
XenEvtchnPort *lp = &s->port_table[interdomain->local_port];
- if (rp->type == EVTCHNSTAT_unbound && rp->type_val == 0) {
- /* It's a match! */
+ /*
+ * The 'remote' port for loopback must be an unbound port allocated for
+ * communication with the local domain (as indicated by rp->type_val
+ * being zero, not PORT_INFO_TYPEVAL_REMOTE_QEMU), and must *not* be
+ * the port that was just allocated for the local end.
+ */
+ if (interdomain->local_port != interdomain->remote_port &&
+ rp->type == EVTCHNSTAT_unbound && rp->type_val == 0) {
+
rp->type = EVTCHNSTAT_interdomain;
rp->type_val = interdomain->local_port;