evtchn/x86: enforce correct upper limit for 32-bit guests
authorJan Beulich <jbeulich@suse.com>
Tue, 22 Sep 2020 14:13:34 +0000 (16:13 +0200)
committerJan Beulich <jbeulich@suse.com>
Tue, 22 Sep 2020 14:13:34 +0000 (16:13 +0200)
commitb8c2efbe7b3e8fa5f0b0a3679afccd1204949070
tree2bbaabddb4087cbf2cbd579a4e9f99184b5c6d97
parentf5469067ee0260673ca1e554ff8888512a55ccfc
evtchn/x86: enforce correct upper limit for 32-bit guests

The recording of d->max_evtchns in evtchn_2l_init(), in particular with
the limited set of callers of the function, is insufficient. Neither for
PV nor for HVM guests the bitness is known at domain_create() time, yet
the upper bound in 2-level mode depends upon guest bitness. Recording
too high a limit "allows" x86 32-bit domains to open not properly usable
event channels, management of which (inside Xen) would then result in
corruption of the shared info and vCPU info structures.

Keep the upper limit dynamic for the 2-level case, introducing a helper
function to retrieve the effective limit. This helper is now supposed to
be private to the event channel code. The used in do_poll() and
domain_dump_evtchn_info() weren't consistent with port uses elsewhere
and hence get switched to port_is_valid().

Furthermore FIFO mode's setup_ports() gets adjusted to loop only up to
the prior ABI limit, rather than all the way up to the new one.

Finally a word on the change to do_poll(): Accessing ->max_evtchns
without holding a suitable lock was never safe, as it as well as
->evtchn_port_ops may change behind do_poll()'s back. Using
port_is_valid() instead widens some the window for potential abuse,
until we've dealt with the race altogether (see XSA-343).

This is XSA-342.

Reported-by: Julien Grall <jgrall@amazon.com>
Fixes: 48974e6ce52e ("evtchn: use a per-domain variable for the max number of event channels")
Signed-off-by: Jan Beulich <jbeulich@suse.com>
Reviewed-by: Stefano Stabellini <sstabellini@kernel.org>
Reviewed-by: Julien Grall <jgrall@amazon.com>
xen/common/event_2l.c
xen/common/event_channel.c
xen/common/event_fifo.c
xen/common/sched/core.c
xen/include/xen/event.h
xen/include/xen/sched.h