summaryrefslogtreecommitdiffstats
path: root/system/xen/xsa/xsa338.patch
diff options
context:
space:
mode:
Diffstat (limited to 'system/xen/xsa/xsa338.patch')
-rw-r--r--system/xen/xsa/xsa338.patch42
1 files changed, 42 insertions, 0 deletions
diff --git a/system/xen/xsa/xsa338.patch b/system/xen/xsa/xsa338.patch
new file mode 100644
index 0000000000..776521990e
--- /dev/null
+++ b/system/xen/xsa/xsa338.patch
@@ -0,0 +1,42 @@
+From: Jan Beulich <jbeulich@suse.com>
+Subject: evtchn: relax port_is_valid()
+
+To avoid ports potentially becoming invalid behind the back of certain
+other functions (due to ->max_evtchn shrinking) because of
+- a guest invoking evtchn_reset() and from a 2nd vCPU opening new
+ channels in parallel (see also XSA-343),
+- alloc_unbound_xen_event_channel() produced channels living above the
+ 2-level range (see also XSA-342),
+drop the max_evtchns check from port_is_valid(). For a port for which
+the function once returned "true", the returned value may not turn into
+"false" later on. The function's result may only depend on bounds which
+can only ever grow (which is the case for d->valid_evtchns).
+
+This also eliminates a false sense of safety, utilized by some of the
+users (see again XSA-343): Without a suitable lock held, d->max_evtchns
+may change at any time, and hence deducing that certain other operations
+are safe when port_is_valid() returned true is not legitimate. The
+opportunities to abuse this may get widened by the change here
+(depending on guest and host configuration), but will be taken care of
+by the other XSA.
+
+This is XSA-338.
+
+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>
+---
+v5: New, split from larger patch.
+
+--- a/xen/include/xen/event.h
++++ b/xen/include/xen/event.h
+@@ -107,8 +107,6 @@ void notify_via_xen_event_channel(struct
+
+ static inline bool_t port_is_valid(struct domain *d, unsigned int p)
+ {
+- if ( p >= d->max_evtchns )
+- return 0;
+ return p < read_atomic(&d->valid_evtchns);
+ }
+