* [PATCH for-8.1] Misc Xen-on-KVM fixes
@ 2023-08-01 17:57 David Woodhouse
2023-08-01 17:57 ` [PATCH for-8.1 1/3] hw/xen: fix off-by-one in xen_evtchn_set_gsi() David Woodhouse
` (3 more replies)
0 siblings, 4 replies; 5+ messages in thread
From: David Woodhouse @ 2023-08-01 17:57 UTC (permalink / raw)
To: qemu-devel
Cc: Paul Durrant, Paolo Bonzini, Richard Henderson, Eduardo Habkost,
Michael S. Tsirkin, Marcel Apfelbaum, Marcelo Tosatti, kvm,
Peter Maydell, Philippe Mathieu-Daudé, Anthony PERARD
A few minor fixes for the Xen emulation support. One was just merged, but
there are three outstanding.
David Woodhouse (3):
hw/xen: fix off-by-one in xen_evtchn_set_gsi()
i386/xen: consistent locking around Xen singleshot timers
hw/xen: prevent guest from binding loopback event channel to itself
hw/i386/kvm/xen_evtchn.c | 15 +++++++++++----
target/i386/kvm/xen-emu.c | 36 ++++++++++++++++++++++++++----------
2 files changed, 37 insertions(+), 14 deletions(-)
^ permalink raw reply [flat|nested] 5+ messages in thread
* [PATCH for-8.1 1/3] hw/xen: fix off-by-one in xen_evtchn_set_gsi()
2023-08-01 17:57 [PATCH for-8.1] Misc Xen-on-KVM fixes David Woodhouse
@ 2023-08-01 17:57 ` David Woodhouse
2023-08-01 17:57 ` [PATCH for-8.1 2/3] i386/xen: consistent locking around Xen singleshot timers David Woodhouse
` (2 subsequent siblings)
3 siblings, 0 replies; 5+ messages in thread
From: David Woodhouse @ 2023-08-01 17:57 UTC (permalink / raw)
To: qemu-devel
Cc: Paul Durrant, Paolo Bonzini, Richard Henderson, Eduardo Habkost,
Michael S. Tsirkin, Marcel Apfelbaum, Marcelo Tosatti, kvm,
Peter Maydell, Philippe Mathieu-Daudé, Anthony PERARD,
David Woodhouse
From: David Woodhouse <dwmw@amazon.co.uk>
Coverity points out (CID 1508128) a bounds checking error. We need to check
for gsi >= IOAPIC_NUM_PINS, not just greater-than.
Also fix up an assert() that has the same problem, that Coverity didn't see.
Fixes: 4f81baa33ed6 ("hw/xen: Support GSI mapping to PIRQ")
Signed-off-by: David Woodhouse <dwmw@amazon.co.uk>
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
---
hw/i386/kvm/xen_evtchn.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/hw/i386/kvm/xen_evtchn.c b/hw/i386/kvm/xen_evtchn.c
index 3d810dbd59..0e9c108614 100644
--- a/hw/i386/kvm/xen_evtchn.c
+++ b/hw/i386/kvm/xen_evtchn.c
@@ -1587,7 +1587,7 @@ static int allocate_pirq(XenEvtchnState *s, int type, int gsi)
found:
pirq_inuse_word(s, pirq) |= pirq_inuse_bit(pirq);
if (gsi >= 0) {
- assert(gsi <= IOAPIC_NUM_PINS);
+ assert(gsi < IOAPIC_NUM_PINS);
s->gsi_pirq[gsi] = pirq;
}
s->pirq[pirq].gsi = gsi;
@@ -1601,7 +1601,7 @@ bool xen_evtchn_set_gsi(int gsi, int level)
assert(qemu_mutex_iothread_locked());
- if (!s || gsi < 0 || gsi > IOAPIC_NUM_PINS) {
+ if (!s || gsi < 0 || gsi >= IOAPIC_NUM_PINS) {
return false;
}
--
2.40.1
^ permalink raw reply related [flat|nested] 5+ messages in thread
* [PATCH for-8.1 2/3] i386/xen: consistent locking around Xen singleshot timers
2023-08-01 17:57 [PATCH for-8.1] Misc Xen-on-KVM fixes David Woodhouse
2023-08-01 17:57 ` [PATCH for-8.1 1/3] hw/xen: fix off-by-one in xen_evtchn_set_gsi() David Woodhouse
@ 2023-08-01 17:57 ` David Woodhouse
2023-08-01 17:57 ` [PATCH for-8.1 3/3] hw/xen: prevent guest from binding loopback event channel to itself David Woodhouse
2023-08-01 21:46 ` [PATCH for-8.1] Misc Xen-on-KVM fixes Philippe Mathieu-Daudé
3 siblings, 0 replies; 5+ messages in thread
From: David Woodhouse @ 2023-08-01 17:57 UTC (permalink / raw)
To: qemu-devel
Cc: Paul Durrant, Paolo Bonzini, Richard Henderson, Eduardo Habkost,
Michael S. Tsirkin, Marcel Apfelbaum, Marcelo Tosatti, kvm,
Peter Maydell, Philippe Mathieu-Daudé, Anthony PERARD,
David Woodhouse
From: David Woodhouse <dwmw@amazon.co.uk>
Coverity points out (CID 1507534, 1507968) that we sometimes access
env->xen_singleshot_timer_ns under the protection of
env->xen_timers_lock and sometimes not.
This isn't always an issue. There are two modes for the timers; if the
kernel supports the EVTCHN_SEND capability then it handles all the timer
hypercalls and delivery internally, and all we use the field for is to
get/set the timer as part of the vCPU state via an ioctl(). If the
kernel doesn't have that support, then we do all the emulation within
qemu, and *those* are the code paths where we actually care about the
locking.
But it doesn't hurt to be a little bit more consistent and avoid having
to explain *why* it's OK.
Signed-off-by: David Woodhouse <dwmw@amazon.co.uk>
Reviewed-by: Paul Durrant <paul@xen.org>
---
target/i386/kvm/xen-emu.c | 36 ++++++++++++++++++++++++++----------
1 file changed, 26 insertions(+), 10 deletions(-)
diff --git a/target/i386/kvm/xen-emu.c b/target/i386/kvm/xen-emu.c
index d7c7eb8d9c..9946ff0905 100644
--- a/target/i386/kvm/xen-emu.c
+++ b/target/i386/kvm/xen-emu.c
@@ -43,6 +43,7 @@
static void xen_vcpu_singleshot_timer_event(void *opaque);
static void xen_vcpu_periodic_timer_event(void *opaque);
+static int vcpuop_stop_singleshot_timer(CPUState *cs);
#ifdef TARGET_X86_64
#define hypercall_compat32(longmode) (!(longmode))
@@ -466,6 +467,7 @@ void kvm_xen_inject_vcpu_callback_vector(uint32_t vcpu_id, int type)
}
}
+/* Must always be called with xen_timers_lock held */
static int kvm_xen_set_vcpu_timer(CPUState *cs)
{
X86CPU *cpu = X86_CPU(cs);
@@ -483,6 +485,7 @@ static int kvm_xen_set_vcpu_timer(CPUState *cs)
static void do_set_vcpu_timer_virq(CPUState *cs, run_on_cpu_data data)
{
+ QEMU_LOCK_GUARD(&X86_CPU(cs)->env.xen_timers_lock);
kvm_xen_set_vcpu_timer(cs);
}
@@ -545,7 +548,6 @@ static void do_vcpu_soft_reset(CPUState *cs, run_on_cpu_data data)
env->xen_vcpu_time_info_gpa = INVALID_GPA;
env->xen_vcpu_runstate_gpa = INVALID_GPA;
env->xen_vcpu_callback_vector = 0;
- env->xen_singleshot_timer_ns = 0;
memset(env->xen_virq, 0, sizeof(env->xen_virq));
set_vcpu_info(cs, INVALID_GPA);
@@ -555,8 +557,13 @@ static void do_vcpu_soft_reset(CPUState *cs, run_on_cpu_data data)
INVALID_GPA);
if (kvm_xen_has_cap(EVTCHN_SEND)) {
kvm_xen_set_vcpu_callback_vector(cs);
+
+ QEMU_LOCK_GUARD(&X86_CPU(cs)->env.xen_timers_lock);
+ env->xen_singleshot_timer_ns = 0;
kvm_xen_set_vcpu_timer(cs);
- }
+ } else {
+ vcpuop_stop_singleshot_timer(cs);
+ };
}
@@ -1059,6 +1066,10 @@ static int vcpuop_stop_periodic_timer(CPUState *target)
return 0;
}
+/*
+ * Userspace handling of timer, for older kernels.
+ * Must always be called with xen_timers_lock held.
+ */
static int do_set_singleshot_timer(CPUState *cs, uint64_t timeout_abs,
bool future, bool linux_wa)
{
@@ -1086,12 +1097,8 @@ static int do_set_singleshot_timer(CPUState *cs, uint64_t timeout_abs,
timeout_abs = now + delta;
}
- qemu_mutex_lock(&env->xen_timers_lock);
-
timer_mod_ns(env->xen_singleshot_timer, qemu_now + delta);
env->xen_singleshot_timer_ns = now + delta;
-
- qemu_mutex_unlock(&env->xen_timers_lock);
return 0;
}
@@ -1115,6 +1122,7 @@ static int vcpuop_set_singleshot_timer(CPUState *cs, uint64_t arg)
return -EFAULT;
}
+ QEMU_LOCK_GUARD(&X86_CPU(cs)->env.xen_timers_lock);
return do_set_singleshot_timer(cs, sst.timeout_abs_ns,
!!(sst.flags & VCPU_SSHOTTMR_future),
false);
@@ -1141,6 +1149,7 @@ static bool kvm_xen_hcall_set_timer_op(struct kvm_xen_exit *exit, X86CPU *cpu,
if (unlikely(timeout == 0)) {
err = vcpuop_stop_singleshot_timer(CPU(cpu));
} else {
+ QEMU_LOCK_GUARD(&X86_CPU(cpu)->env.xen_timers_lock);
err = do_set_singleshot_timer(CPU(cpu), timeout, false, true);
}
exit->u.hcall.result = err;
@@ -1826,6 +1835,7 @@ int kvm_put_xen_state(CPUState *cs)
* If the kernel has EVTCHN_SEND support then it handles timers too,
* so the timer will be restored by kvm_xen_set_vcpu_timer() below.
*/
+ QEMU_LOCK_GUARD(&env->xen_timers_lock);
if (env->xen_singleshot_timer_ns) {
ret = do_set_singleshot_timer(cs, env->xen_singleshot_timer_ns,
false, false);
@@ -1844,10 +1854,7 @@ int kvm_put_xen_state(CPUState *cs)
}
if (env->xen_virq[VIRQ_TIMER]) {
- ret = kvm_xen_set_vcpu_timer(cs);
- if (ret < 0) {
- return ret;
- }
+ do_set_vcpu_timer_virq(cs, RUN_ON_CPU_HOST_INT(env->xen_virq[VIRQ_TIMER]));
}
return 0;
}
@@ -1896,6 +1903,15 @@ int kvm_get_xen_state(CPUState *cs)
if (ret < 0) {
return ret;
}
+
+ /*
+ * This locking is fairly pointless, and is here to appease Coverity.
+ * There is an unavoidable race condition if a different vCPU sets a
+ * timer for this vCPU after the value has been read out. But that's
+ * OK in practice because *all* the vCPUs need to be stopped before
+ * we set about migrating their state.
+ */
+ QEMU_LOCK_GUARD(&X86_CPU(cs)->env.xen_timers_lock);
env->xen_singleshot_timer_ns = va.u.timer.expires_ns;
}
--
2.40.1
^ permalink raw reply related [flat|nested] 5+ messages in thread
* [PATCH for-8.1 3/3] hw/xen: prevent guest from binding loopback event channel to itself
2023-08-01 17:57 [PATCH for-8.1] Misc Xen-on-KVM fixes David Woodhouse
2023-08-01 17:57 ` [PATCH for-8.1 1/3] hw/xen: fix off-by-one in xen_evtchn_set_gsi() David Woodhouse
2023-08-01 17:57 ` [PATCH for-8.1 2/3] i386/xen: consistent locking around Xen singleshot timers David Woodhouse
@ 2023-08-01 17:57 ` David Woodhouse
2023-08-01 21:46 ` [PATCH for-8.1] Misc Xen-on-KVM fixes Philippe Mathieu-Daudé
3 siblings, 0 replies; 5+ messages in thread
From: David Woodhouse @ 2023-08-01 17:57 UTC (permalink / raw)
To: qemu-devel
Cc: Paul Durrant, Paolo Bonzini, Richard Henderson, Eduardo Habkost,
Michael S. Tsirkin, Marcel Apfelbaum, Marcelo Tosatti, kvm,
Peter Maydell, Philippe Mathieu-Daudé, Anthony PERARD,
David Woodhouse
From: David Woodhouse <dwmw@amazon.co.uk>
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>
---
hw/i386/kvm/xen_evtchn.c | 11 +++++++++--
1 file changed, 9 insertions(+), 2 deletions(-)
diff --git a/hw/i386/kvm/xen_evtchn.c b/hw/i386/kvm/xen_evtchn.c
index 0e9c108614..a731738411 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;
--
2.40.1
^ permalink raw reply related [flat|nested] 5+ messages in thread
* Re: [PATCH for-8.1] Misc Xen-on-KVM fixes
2023-08-01 17:57 [PATCH for-8.1] Misc Xen-on-KVM fixes David Woodhouse
` (2 preceding siblings ...)
2023-08-01 17:57 ` [PATCH for-8.1 3/3] hw/xen: prevent guest from binding loopback event channel to itself David Woodhouse
@ 2023-08-01 21:46 ` Philippe Mathieu-Daudé
3 siblings, 0 replies; 5+ messages in thread
From: Philippe Mathieu-Daudé @ 2023-08-01 21:46 UTC (permalink / raw)
To: David Woodhouse, qemu-devel
Cc: Paul Durrant, Paolo Bonzini, Richard Henderson, Eduardo Habkost,
Michael S. Tsirkin, Marcel Apfelbaum, Marcelo Tosatti, kvm,
Peter Maydell, Anthony PERARD
On 1/8/23 19:57, David Woodhouse wrote:
> A few minor fixes for the Xen emulation support. One was just merged, but
> there are three outstanding.
>
> David Woodhouse (3):
> hw/xen: fix off-by-one in xen_evtchn_set_gsi()
> i386/xen: consistent locking around Xen singleshot timers
> hw/xen: prevent guest from binding loopback event channel to itself
>
> hw/i386/kvm/xen_evtchn.c | 15 +++++++++++----
> target/i386/kvm/xen-emu.c | 36 ++++++++++++++++++++++++++----------
> 2 files changed, 37 insertions(+), 14 deletions(-)
Thanks, since the series is reviewed, I'm queuing via misc-fixes.
^ permalink raw reply [flat|nested] 5+ messages in thread
end of thread, other threads:[~2023-08-01 21:46 UTC | newest]
Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2023-08-01 17:57 [PATCH for-8.1] Misc Xen-on-KVM fixes David Woodhouse
2023-08-01 17:57 ` [PATCH for-8.1 1/3] hw/xen: fix off-by-one in xen_evtchn_set_gsi() David Woodhouse
2023-08-01 17:57 ` [PATCH for-8.1 2/3] i386/xen: consistent locking around Xen singleshot timers David Woodhouse
2023-08-01 17:57 ` [PATCH for-8.1 3/3] hw/xen: prevent guest from binding loopback event channel to itself David Woodhouse
2023-08-01 21:46 ` [PATCH for-8.1] Misc Xen-on-KVM fixes Philippe Mathieu-Daudé
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).