evtchn/x86: enforce correct upper limit for 32-bit guests
authorJan Beulich <jbeulich@suse.com>
Tue, 22 Sep 2020 13:50:09 +0000 (15:50 +0200)
committerJan Beulich <jbeulich@suse.com>
Tue, 22 Sep 2020 13:50:09 +0000 (15:50 +0200)
commit62bcdc4edbf6d8c6e8a25544d48de22ccf75310d
treef2fa4752961c395f7e79ed2f1c41afbbd1dbc667
parent112992b05b2d2ca63f3c78eefe1cf8d192d7303a
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