Compare commits

...
Sign in to create a new pull request.

15 commits

Author SHA1 Message Date
Michael Young
f72515dd8b update to xen-4.13.3 2021-03-29 22:30:31 +01:00
Michael Young
7490b76e19 HVM soft-reset crashes toolstack [XSA-368, CVE-2021-28687] (#1940610) 2021-03-18 21:32:03 +00:00
Michael Young
c3863c816e Linux: display frontend "be-alloc" mode is unsupported (comment only)
[XSA-363, CVE-2021-26934] (#1929549)
arm: The cache may not be cleaned for newly allocated scrubbed pages
      [XSA-364, CVE-2021-26933] (#1929547)
2021-02-17 22:17:51 +00:00
Michael Young
37608f5d89 IRQ vector leak on x86 [XSA-360] 2021-01-21 21:38:50 +00:00
Michael Young
24e155b60d multiple security updates
xenstore watch notifications lacking permission checks [XSA-115,
	CVE-2020-29480] (#1908091)
Xenstore: new domains inheriting existing node permissions [XSA-322,
	CVE-2020-29481] (#1908095)
Xenstore: wrong path length check [XSA-323, CVE-2020-29482] (#1908096)
Xenstore: guests can crash xenstored via watchs [XSA-324, CVE-2020-29484]
	(#1908088)
Xenstore: guests can disturb domain cleanup [XSA-325, CVE-2020-29483]
	(#1908087)
oxenstored memory leak in reset_watches [XSA-330, CVE-2020-29485]
	(#1908000)
undue recursion in x86 HVM context switch code [XSA-348, CVE-2020-29566]
	(#1908085)
oxenstored: node ownership can be changed by unprivileged clients
	[XSA-352, CVE-2020-29486] (#1908003)
oxenstored: permissions not checked on root node [XSA-353, CVE-2020-29479]
	(#1908002)
FIFO event channels control block related ordering [XSA-358,
	CVE-2020-29570] (#1907931)
FIFO event channels control structure ordering [XSA-359, CVE-2020-29571]
	(#1908089)
2020-12-16 21:12:53 +00:00
Michael Young
86dbccba26 stack corruption from XSA-346 change [XSA-355] 2020-11-24 20:10:47 +00:00
Michael Young
aa6e17cc27 support zstd compressed kernels (dom0 only) based on linux kernel code 2020-11-23 23:07:44 +00:00
Michael Young
6f9b812905 add CVE and bug reference 2020-11-12 20:26:12 +00:00
Michael Young
fc3d63c3dc Information leak via power sidechannel [XSA-351] 2020-11-10 22:31:53 +00:00
Michael Young
5f155647b3 update to xen-4.13.2 2020-11-03 21:49:13 +00:00
Michael Young
e7122f27e1 add some CVE/bug references 2020-10-28 22:42:19 +00:00
Michael Young
0af4083600 x86 PV guest INVLPG-like flushes may leave stale TLB entries
[XSA-286, CVE-2020-27674] (#1891092)
2020-10-28 22:37:41 +00:00
Michael Young
298b801f9a 3 security updates
x86: Race condition in Xen mapping code [XSA-345]
undue deferral of IOMMU TLB flushes [XSA-346]
unsafe AMD IOMMU page table updates [XSA-347]
2020-10-20 20:13:39 +01:00
Michael Young
39685fac18 10 security fixes
x86 pv: Crash when handling guest access to MSR_MISC_ENABLE [XSA-333,
	CVE-2020-25602] (#1881619)
Missing unlock in XENMEM_acquire_resource error path [XSA-334,
	CVE-2020-25598] (#1881616)
race when migrating timers between x86 HVM vCPU-s [XSA-336,
	CVE-2020-25604] (#1881618)
PCI passthrough code reading back hardware registers [XSA-337,
	CVE-2020-25595] (#1881587)
once valid event channels may not turn invalid [XSA-338, CVE-2020-25597]
	(#1881588)
x86 pv guest kernel DoS via SYSENTER [XSA-339, CVE-2020-25596]
	(#1881617)
Missing memory barriers when accessing/allocating an event channel [XSA-340,
	CVE-2020-25603] (#1881583)
out of bounds event channels available to 32-bit x86 domains [XSA-342,
	CVE-2020-25600] (#1881582)
races with evtchn_reset() [XSA-343, CVE-2020-25599] (#1881581)
lack of preemption in evtchn_reset() / evtchn_destroy() [XSA-344,
	CVE-2020-25601] (#1881586)
2020-09-22 21:05:24 +01:00
Michael Young
22d02a7039 QEMU: usb: out-of-bounds r/w access issue [XSA-335, CVE-2020-14364]
(#1871850)
2020-08-25 15:27:58 +01:00
23 changed files with 9345 additions and 1321 deletions

2
.gitignore vendored
View file

@ -6,4 +6,4 @@ lwip-1.3.0.tar.gz
pciutils-2.2.9.tar.bz2
zlib-1.2.3.tar.gz
polarssl-1.1.4-gpl.tgz
/xen-4.13.1.tar.gz
/xen-4.13.3.tar.gz

View file

@ -4,4 +4,4 @@ SHA512 (newlib-1.16.0.tar.gz) = 40eb96bbc6736a16b6399e0cdb73e853d0d90b685c967e77
SHA512 (zlib-1.2.3.tar.gz) = 021b958fcd0d346c4ba761bcf0cc40f3522de6186cf5a0a6ea34a70504ce9622b1c2626fce40675bc8282cf5f5ade18473656abc38050f72f5d6480507a2106e
SHA512 (polarssl-1.1.4-gpl.tgz) = 88da614e4d3f4409c4fd3bb3e44c7587ba051e3fed4e33d526069a67e8180212e1ea22da984656f50e290049f60ddca65383e5983c0f8884f648d71f698303ad
SHA512 (pciutils-2.2.9.tar.bz2) = 2b3d98d027e46d8c08037366dde6f0781ca03c610ef2b380984639e4ef39899ed8d8b8e4cd9c9dc54df101279b95879bd66bfd4d04ad07fef41e847ea7ae32b5
SHA512 (xen-4.13.1.tar.gz) = b56d20704155d98d803496cba83eb928e0f986a750831cd5600fc88d0ae772fe1456571654375054043d2da8daca255cc98385ebf08b1b1a75ecf7f4b7a0ee90
SHA512 (xen-4.13.3.tar.gz) = 622127d824b9c49b57282a887fb404e0bad05ff60bccade82e4e0e9b5ad975ff9aa1fba83392e6d8379e9a15340e8ae9785c0913eb11027816e4600432eea6b6

View file

@ -38,17 +38,17 @@
return get_node(conn, ctx, *canonical_name, perm);
}
--- xen-4.9.0-rc1.2/tools/xenstore/xenstored_core.h.orig 2017-04-12 16:18:57.000000000 +0100
+++ xen-4.9.0-rc1.2/tools/xenstore/xenstored_core.h 2017-04-13 21:20:29.146368478 +0100
@@ -148,7 +148,7 @@
--- xen-4.13.3/tools/xenstore/xenstored_core.h.orig 2021-03-22 16:57:42.000000000 +0000
+++ xen-4.13.3/tools/xenstore/xenstored_core.h 2021-03-29 19:56:36.642394283 +0100
@@ -153,7 +153,7 @@
void send_ack(struct connection *conn, enum xsd_sockmsg_type type);
/* Canonicalize this path if possible. */
-char *canonicalize(struct connection *conn, const void *ctx, const char *node);
+char *xenstore_canonicalize(struct connection *conn, const void *ctx, const char *node);
/* Write a node to the tdb data base. */
int write_node_raw(struct connection *conn, TDB_DATA *key, struct node *node);
/* Get access permissions. */
enum xs_perm_type perm_for_conn(struct connection *conn,
--- xen-4.8.0/tools/console/testsuite/console-dom0.c.orig 2016-12-05 12:03:27.000000000 +0000
+++ xen-4.8.0/tools/console/testsuite/console-dom0.c 2017-02-26 21:52:24.554678631 +0000
@@ -18,7 +18,7 @@

View file

@ -1,65 +0,0 @@
--- xen-4.13.0/tools/xenstore/utils.h.orig 2019-12-17 14:23:09.000000000 +0000
+++ xen-4.13.0/tools/xenstore/utils.h 2020-01-21 21:13:05.108957447 +0000
@@ -24,7 +24,7 @@
void barf(const char *fmt, ...) __attribute__((noreturn));
void barf_perror(const char *fmt, ...) __attribute__((noreturn));
-void (*xprintf)(const char *fmt, ...);
+extern void (*xprintf)(const char *fmt, ...);
#define eprintf(_fmt, _args...) xprintf("[ERR] %s" _fmt, __FUNCTION__, ##_args)
--- xen-4.13.0/tools/xenstore/xenstored_core.h.orig 2020-01-21 21:15:19.243931307 +0000
+++ xen-4.13.0/tools/xenstore/xenstored_core.h 2020-01-21 21:38:35.340617819 +0000
@@ -204,7 +204,7 @@
/* Open a pipe for signal handling */
void init_pipe(int reopen_log_pipe[2]);
-xengnttab_handle **xgt_handle;
+extern xengnttab_handle **xgt_handle;
int remember_string(struct hashtable *hash, const char *str);
--- xen-4.13.0/tools/libxl/libxlu_pci.c.orig 2019-12-17 14:23:09.000000000 +0000
+++ xen-4.13.0/tools/libxl/libxlu_pci.c 2020-01-21 21:56:26.812212916 +0000
@@ -48,7 +48,7 @@
int xlu_pci_parse_bdf(XLU_Config *cfg, libxl_device_pci *pcidev, const char *str)
{
unsigned state = STATE_DOMAIN;
- unsigned dom, bus, dev, func, vslot = 0;
+ unsigned dom = 0, bus = 0, dev = 0, func = 0, vslot = 0;
char *buf2, *tok, *ptr, *end, *optkey = NULL;
if ( NULL == (buf2 = ptr = strdup(str)) )
--- xen-4.13.0/tools/libxl/libxl_utils.c.orig 2019-12-17 14:23:09.000000000 +0000
+++ xen-4.13.0/tools/libxl/libxl_utils.c 2020-01-21 22:34:52.096300774 +0000
@@ -1259,7 +1259,7 @@
}
memset(un, 0, sizeof(struct sockaddr_un));
un->sun_family = AF_UNIX;
- strncpy(un->sun_path, path, sizeof(un->sun_path));
+ strncpy(un->sun_path, path, sizeof(un->sun_path)-1);
return 0;
}
--- xen-4.13.0/tools/debugger/kdd/kdd.h.orig 2019-12-17 14:23:09.000000000 +0000
+++ xen-4.13.0/tools/debugger/kdd/kdd.h 2020-01-21 23:35:55.458605582 +0000
@@ -323,7 +323,7 @@
kdd_msg msg;
kdd_reg reg;
kdd_stc stc;
- uint8_t payload[0];
+ uint8_t payload[65535];
};
} PACKED kdd_pkt;
--- xen-4.13.0/tools/xenpmd/Makefile.orig 2019-12-17 14:23:09.000000000 +0000
+++ xen-4.13.0/tools/xenpmd/Makefile 2020-01-22 22:13:16.564873608 +0000
@@ -3,6 +3,7 @@
CFLAGS += -Werror
CFLAGS += $(CFLAGS_libxenstore)
+CFLAGS += -Wno-error=format-truncation
LDLIBS += $(LDLIBS_libxenstore)

View file

@ -103,8 +103,10 @@ CONFIG_HARDEN_BRANCH_PREDICTOR=y
CONFIG_ARM64_ERRATUM_827319=y
CONFIG_ARM64_ERRATUM_824069=y
CONFIG_ARM64_ERRATUM_819472=y
CONFIG_ARM64_ERRATUM_843419=y
CONFIG_ARM64_ERRATUM_832075=y
CONFIG_ARM64_ERRATUM_834220=y
CONFIG_ARM_ERRATUM_858921=y
CONFIG_ARM64_HARDEN_BRANCH_PREDICTOR=y
CONFIG_ALL_PLAT=y
# CONFIG_QEMU is not set

View file

@ -13,7 +13,7 @@
ret = xc_vcpu_getcontext(_H(xch), _D(domid), Int_val(cpu), &ctxt);
context = caml_alloc_string(sizeof(ctxt));
- memcpy(String_val(context), (char *) &ctxt.c, sizeof(ctxt.c));
- memcpy((char *) String_val(context), &ctxt.c, sizeof(ctxt.c));
+ memcpy((char *) Bp_val(context), (char *) &ctxt.c, sizeof(ctxt.c));
CAMLreturn(context);
@ -22,7 +22,7 @@
conring_size = size;
ring = caml_alloc_string(count);
- memcpy(String_val(ring), str, count);
- memcpy((char *) String_val(ring), str, count);
+ memcpy((char *) Bp_val(ring), str, count);
free(str);
@ -45,33 +45,13 @@
r = xc_cpuid_set(_H(xch), _D(domid),
c_input, (const char **)c_config, out_config);
--- xen-4.13.0/tools/ocaml/libs/xb/xs_ring_stubs.c.orig 2019-12-17 14:23:09.000000000 +0000
+++ xen-4.13.0/tools/ocaml/libs/xb/xs_ring_stubs.c 2020-01-21 23:51:35.473330934 +0000
@@ -44,7 +44,7 @@
CAMLlocal1(ml_result);
struct mmap_interface *interface = GET_C_STRUCT(ml_interface);
- char *buffer = String_val(ml_buffer);
+ char *buffer = (char *) Bp_val(ml_buffer);
int len = Int_val(ml_len);
int result;
@@ -103,7 +103,7 @@
CAMLlocal1(ml_result);
struct mmap_interface *interface = GET_C_STRUCT(ml_interface);
- char *buffer = String_val(ml_buffer);
+ char *buffer = (char *) Bp_val(ml_buffer);
int len = Int_val(ml_len);
int result;
--- xen-4.13.0/tools/ocaml/libs/xb/xenbus_stubs.c.orig 2019-12-17 14:23:09.000000000 +0000
+++ xen-4.13.0/tools/ocaml/libs/xb/xenbus_stubs.c 2020-01-22 00:04:09.443168991 +0000
@@ -65,7 +65,7 @@
};
ret = caml_alloc_string(sizeof(struct xsd_sockmsg));
- memcpy(String_val(ret), &xsd, sizeof(struct xsd_sockmsg));
- memcpy((char *) String_val(ret), &xsd, sizeof(struct xsd_sockmsg));
+ memcpy((char *) Bp_val(ret), &xsd, sizeof(struct xsd_sockmsg));
CAMLreturn(ret);

129
xen.spec
View file

@ -57,8 +57,8 @@
Summary: Xen is a virtual machine monitor
Name: xen
Version: 4.13.1
Release: 4%{?dist}
Version: 4.13.3
Release: 1%{?dist}
License: GPLv2+ and LGPLv2+ and BSD
URL: http://xen.org/
Source0: https://downloads.xenproject.org/release/xen/%{version}/xen-%{version}.tar.gz
@ -113,21 +113,8 @@ Patch40: xen.drop.brctl.patch
Patch41: xen.python.env.patch
Patch42: xen.gcc9.fixes.patch
Patch44: xen.ocaml.4.10.patch
Patch45: xen.gcc10.fixes.patch
Patch46: xsa320-4.13-1.patch
Patch47: xsa320-4.13-2.patch
Patch48: xsa317.patch
Patch49: xsa319.patch
Patch50: xsa328-4.13-1.patch
Patch51: xsa328-4.13-2.patch
Patch52: xsa321-4.13-1.patch
Patch53: xsa321-4.13-2.patch
Patch54: xsa321-4.13-3.patch
Patch55: xsa321-4.13-4.patch
Patch56: xsa321-4.13-5.patch
Patch57: xsa321-4.13-6.patch
Patch58: xsa321-4.13-7.patch
Patch59: xsa327.patch
Patch65: zstd-dom0.patch
Patch100: xsa363.patch
%if %build_qemutrad
@ -333,21 +320,8 @@ manage Xen virtual machines.
%patch41 -p1
%patch42 -p1
%patch44 -p1
%patch45 -p1
%patch46 -p1
%patch47 -p1
%patch48 -p1
%patch49 -p1
%patch50 -p1
%patch51 -p1
%patch52 -p1
%patch53 -p1
%patch54 -p1
%patch55 -p1
%patch56 -p1
%patch57 -p1
%patch58 -p1
%patch59 -p1
%patch65 -p1
%patch100 -p1
# qemu-xen-traditional patches
pushd tools/qemu-xen-traditional
@ -940,6 +914,97 @@ fi
%endif
%changelog
* Mon Mar 29 2021 Michael Young <m.a.young@durham.ac.uk> - 4.13.3-1
- update to 4.13.3
remove patches now included or superceded upstream
adjust xen.hypervisor.config
* Thu Mar 18 2021 Michael Young <m.a.young@durham.ac.uk> - 4.13.2-8
- HVM soft-reset crashes toolstack [XSA-368, CVE-2021-28687] (#1940610)
* Wed Feb 17 2021 Michael Young <m.a.young@durham.ac.uk> - 4.13.2-7
- Linux: display frontend "be-alloc" mode is unsupported (comment only)
[XSA-363, CVE-2021-26934] (#1929549)
- arm: The cache may not be cleaned for newly allocated scrubbed pages
[XSA-364, CVE-2021-26933] (#1929547)
* Thu Jan 21 2021 Michael Young <m.a.young@durham.ac.uk> - 4.13.2-6
- IRQ vector leak on x86 [XSA-360]
* Wed Dec 16 2020 Michael Young <m.a.young@durham.ac.uk> - 4.13.2-5
- xenstore watch notifications lacking permission checks [XSA-115,
CVE-2020-29480] (#1908091)
- Xenstore: new domains inheriting existing node permissions [XSA-322,
CVE-2020-29481] (#1908095)
- Xenstore: wrong path length check [XSA-323, CVE-2020-29482] (#1908096)
- Xenstore: guests can crash xenstored via watchs [XSA-324, CVE-2020-29484]
(#1908088)
- Xenstore: guests can disturb domain cleanup [XSA-325, CVE-2020-29483]
(#1908087)
- oxenstored memory leak in reset_watches [XSA-330, CVE-2020-29485]
(#1908000)
- undue recursion in x86 HVM context switch code [XSA-348, CVE-2020-29566]
(#1908085)
- oxenstored: node ownership can be changed by unprivileged clients
[XSA-352, CVE-2020-29486] (#1908003)
- oxenstored: permissions not checked on root node [XSA-353, CVE-2020-29479]
(#1908002)
- FIFO event channels control block related ordering [XSA-358,
CVE-2020-29570] (#1907931)
- FIFO event channels control structure ordering [XSA-359, CVE-2020-29571]
(#1908089)
* Tue Nov 24 2020 Michael Young <m.a.young@durham.ac.uk> - 4.13.2-4
- stack corruption from XSA-346 change [XSA-355]
* Mon Nov 23 2020 Michael Young <m.a.young@durham.ac.uk> - 4.13.2-3
- support zstd compressed kernels (dom0 only) based on linux kernel code
* Tue Nov 10 2020 Michael Young <m.a.young@durham.ac.uk> - 4.13.2-2
- Information leak via power sidechannel [XSA-351, CVE-2020-28368]
(#1897146)
* Tue Nov 03 2020 Michael Young <m.a.young@durham.ac.uk> - 4.13.2-1
- update to 4.13.2
remove patches now included or superceded upstream
* Wed Oct 28 2020 Michael Young <m.a.young@durham.ac.uk> - 4.13.1-8
- x86 PV guest INVLPG-like flushes may leave stale TLB entries
[XSA-286, CVE-2020-27674] (#1891092)
* Tue Oct 20 2020 Michael Young <m.a.young@durham.ac.uk> - 4.13.1-7
- x86: Race condition in Xen mapping code [XSA-345, CVE-2020-27672]
(#1891097)
- undue deferral of IOMMU TLB flushes [XSA-346, CVE-2020-27671]
(#1891093)
- unsafe AMD IOMMU page table updates [XSA-347 CVE-2020-27670]
(#1891088)
* Tue Sep 22 2020 Michael Young <m.a.young@durham.ac.uk> - 4.13.1-6
- x86 pv: Crash when handling guest access to MSR_MISC_ENABLE [XSA-333,
CVE-2020-25602] (#1881619)
- Missing unlock in XENMEM_acquire_resource error path [XSA-334,
CVE-2020-25598] (#1881616)
- race when migrating timers between x86 HVM vCPU-s [XSA-336,
CVE-2020-25604] (#1881618)
- PCI passthrough code reading back hardware registers [XSA-337,
CVE-2020-25595] (#1881587)
- once valid event channels may not turn invalid [XSA-338, CVE-2020-25597]
(#1881588)
- x86 pv guest kernel DoS via SYSENTER [XSA-339, CVE-2020-25596]
(#1881617)
- Missing memory barriers when accessing/allocating an event channel [XSA-340,
CVE-2020-25603] (#1881583)
- out of bounds event channels available to 32-bit x86 domains [XSA-342,
CVE-2020-25600] (#1881582)
- races with evtchn_reset() [XSA-343, CVE-2020-25599] (#1881581)
- lack of preemption in evtchn_reset() / evtchn_destroy() [XSA-344,
CVE-2020-25601] (#1881586)
* Tue Aug 25 2020 Michael Young <m.a.young@durham.ac.uk> - 4.13.1-5
- QEMU: usb: out-of-bounds r/w access issue [XSA-335, CVE-2020-14364]
(#1871850)
* Tue Jul 07 2020 Michael Young <m.a.young@durham.ac.uk> - 4.13.1-4
- incorrect error handling in event channel port allocation leads to
DoS [XSA-317, CVE-2020-15566] (#1854465)

View file

@ -1,50 +0,0 @@
From aeb46e92f915f19a61d5a8a1f4b696793f64e6fb Mon Sep 17 00:00:00 2001
From: Julien Grall <jgrall@amazon.com>
Date: Thu, 19 Mar 2020 13:17:31 +0000
Subject: [PATCH] xen/common: event_channel: Don't ignore error in
get_free_port()
Currently, get_free_port() is assuming that the port has been allocated
when evtchn_allocate_port() is not return -EBUSY.
However, the function may return an error when:
- We exhausted all the event channels. This can happen if the limit
configured by the administrator for the guest ('max_event_channels'
in xl cfg) is higher than the ABI used by the guest. For instance,
if the guest is using 2L, the limit should not be higher than 4095.
- We cannot allocate memory (e.g Xen has not more memory).
Users of get_free_port() (such as EVTCHNOP_alloc_unbound) will validly
assuming the port was valid and will next call evtchn_from_port(). This
will result to a crash as the memory backing the event channel structure
is not present.
Fixes: 368ae9a05fe ("xen/pvshim: forward evtchn ops between L0 Xen and L2 DomU")
Signed-off-by: Julien Grall <jgrall@amazon.com>
Reviewed-by: Jan Beulich <jbeulich@suse.com>
---
xen/common/event_channel.c | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/xen/common/event_channel.c b/xen/common/event_channel.c
index e86e2bfab0..a8d182b584 100644
--- a/xen/common/event_channel.c
+++ b/xen/common/event_channel.c
@@ -195,10 +195,10 @@ static int get_free_port(struct domain *d)
{
int rc = evtchn_allocate_port(d, port);
- if ( rc == -EBUSY )
- continue;
-
- return port;
+ if ( rc == 0 )
+ return port;
+ else if ( rc != -EBUSY )
+ return rc;
}
return -ENOSPC;
--
2.17.1

View file

@ -1,27 +0,0 @@
From: Jan Beulich <jbeulich@suse.com>
Subject: x86/shadow: correct an inverted conditional in dirty VRAM tracking
This originally was "mfn_x(mfn) == INVALID_MFN". Make it like this
again, taking the opportunity to also drop the unnecessary nearby
braces.
This is XSA-319.
Fixes: 246a5a3377c2 ("xen: Use a typesafe to define INVALID_MFN")
Signed-off-by: Jan Beulich <jbeulich@suse.com>
Reviewed-by: Andrew Cooper <andrew.cooper3@citrix.com>
--- a/xen/arch/x86/mm/shadow/common.c
+++ b/xen/arch/x86/mm/shadow/common.c
@@ -3252,10 +3252,8 @@ int shadow_track_dirty_vram(struct domai
int dirty = 0;
paddr_t sl1ma = dirty_vram->sl1ma[i];
- if ( !mfn_eq(mfn, INVALID_MFN) )
- {
+ if ( mfn_eq(mfn, INVALID_MFN) )
dirty = 1;
- }
else
{
page = mfn_to_page(mfn);

View file

@ -1,117 +0,0 @@
From: Andrew Cooper <andrew.cooper3@citrix.com>
Subject: x86/spec-ctrl: CPUID/MSR definitions for Special Register Buffer Data Sampling
This is part of XSA-320 / CVE-2020-0543
Signed-off-by: Andrew Cooper <andrew.cooper3@citrix.com>
Reviewed-by: Jan Beulich <jbeulich@suse.com>
Acked-by: Wei Liu <wl@xen.org>
diff --git a/docs/misc/xen-command-line.pandoc b/docs/misc/xen-command-line.pandoc
index 1d9d816622..9268454297 100644
--- a/docs/misc/xen-command-line.pandoc
+++ b/docs/misc/xen-command-line.pandoc
@@ -483,10 +483,10 @@ accounting for hardware capabilities as enumerated via CPUID.
Currently accepted:
-The Speculation Control hardware features `md-clear`, `ibrsb`, `stibp`, `ibpb`,
-`l1d-flush` and `ssbd` are used by default if available and applicable. They can
-be ignored, e.g. `no-ibrsb`, at which point Xen won't use them itself, and
-won't offer them to guests.
+The Speculation Control hardware features `srbds-ctrl`, `md-clear`, `ibrsb`,
+`stibp`, `ibpb`, `l1d-flush` and `ssbd` are used by default if available and
+applicable. They can be ignored, e.g. `no-ibrsb`, at which point Xen won't
+use them itself, and won't offer them to guests.
### cpuid_mask_cpu
> `= fam_0f_rev_[cdefg] | fam_10_rev_[bc] | fam_11_rev_b`
diff --git a/tools/libxl/libxl_cpuid.c b/tools/libxl/libxl_cpuid.c
index 6cea4227ba..a78f08b927 100644
--- a/tools/libxl/libxl_cpuid.c
+++ b/tools/libxl/libxl_cpuid.c
@@ -213,6 +213,7 @@ int libxl_cpuid_parse_config(libxl_cpuid_policy_list *cpuid, const char* str)
{"avx512-4vnniw",0x00000007, 0, CPUID_REG_EDX, 2, 1},
{"avx512-4fmaps",0x00000007, 0, CPUID_REG_EDX, 3, 1},
+ {"srbds-ctrl", 0x00000007, 0, CPUID_REG_EDX, 9, 1},
{"md-clear", 0x00000007, 0, CPUID_REG_EDX, 10, 1},
{"cet-ibt", 0x00000007, 0, CPUID_REG_EDX, 20, 1},
{"ibrsb", 0x00000007, 0, CPUID_REG_EDX, 26, 1},
diff --git a/tools/misc/xen-cpuid.c b/tools/misc/xen-cpuid.c
index 603e1d65fd..a09440813b 100644
--- a/tools/misc/xen-cpuid.c
+++ b/tools/misc/xen-cpuid.c
@@ -157,6 +157,7 @@ static const char *const str_7d0[32] =
[ 2] = "avx512_4vnniw", [ 3] = "avx512_4fmaps",
[ 4] = "fsrm",
+ /* 8 */ [ 9] = "srbds-ctrl",
[10] = "md-clear",
/* 12 */ [13] = "tsx-force-abort",
diff --git a/xen/arch/x86/msr.c b/xen/arch/x86/msr.c
index 4b12103482..0cded3c0ad 100644
--- a/xen/arch/x86/msr.c
+++ b/xen/arch/x86/msr.c
@@ -134,6 +134,7 @@ int guest_rdmsr(struct vcpu *v, uint32_t msr, uint64_t *val)
/* Write-only */
case MSR_TSX_FORCE_ABORT:
case MSR_TSX_CTRL:
+ case MSR_MCU_OPT_CTRL:
case MSR_U_CET:
case MSR_S_CET:
case MSR_PL0_SSP ... MSR_INTERRUPT_SSP_TABLE:
@@ -288,6 +289,7 @@ int guest_wrmsr(struct vcpu *v, uint32_t msr, uint64_t val)
/* Read-only */
case MSR_TSX_FORCE_ABORT:
case MSR_TSX_CTRL:
+ case MSR_MCU_OPT_CTRL:
case MSR_U_CET:
case MSR_S_CET:
case MSR_PL0_SSP ... MSR_INTERRUPT_SSP_TABLE:
diff --git a/xen/arch/x86/spec_ctrl.c b/xen/arch/x86/spec_ctrl.c
index 6656c44aec..5fc1c6827e 100644
--- a/xen/arch/x86/spec_ctrl.c
+++ b/xen/arch/x86/spec_ctrl.c
@@ -312,12 +312,13 @@ static void __init print_details(enum ind_thunk thunk, uint64_t caps)
printk("Speculative mitigation facilities:\n");
/* Hardware features which pertain to speculative mitigations. */
- printk(" Hardware features:%s%s%s%s%s%s%s%s%s%s%s%s%s%s\n",
+ printk(" Hardware features:%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s\n",
(_7d0 & cpufeat_mask(X86_FEATURE_IBRSB)) ? " IBRS/IBPB" : "",
(_7d0 & cpufeat_mask(X86_FEATURE_STIBP)) ? " STIBP" : "",
(_7d0 & cpufeat_mask(X86_FEATURE_L1D_FLUSH)) ? " L1D_FLUSH" : "",
(_7d0 & cpufeat_mask(X86_FEATURE_SSBD)) ? " SSBD" : "",
(_7d0 & cpufeat_mask(X86_FEATURE_MD_CLEAR)) ? " MD_CLEAR" : "",
+ (_7d0 & cpufeat_mask(X86_FEATURE_SRBDS_CTRL)) ? " SRBDS_CTRL" : "",
(e8b & cpufeat_mask(X86_FEATURE_IBPB)) ? " IBPB" : "",
(caps & ARCH_CAPS_IBRS_ALL) ? " IBRS_ALL" : "",
(caps & ARCH_CAPS_RDCL_NO) ? " RDCL_NO" : "",
diff --git a/xen/include/asm-x86/msr-index.h b/xen/include/asm-x86/msr-index.h
index 7693c4a71a..91994669e1 100644
--- a/xen/include/asm-x86/msr-index.h
+++ b/xen/include/asm-x86/msr-index.h
@@ -179,6 +179,9 @@
#define MSR_IA32_VMX_TRUE_ENTRY_CTLS 0x490
#define MSR_IA32_VMX_VMFUNC 0x491
+#define MSR_MCU_OPT_CTRL 0x00000123
+#define MCU_OPT_CTRL_RNGDS_MITG_DIS (_AC(1, ULL) << 0)
+
#define MSR_U_CET 0x000006a0
#define MSR_S_CET 0x000006a2
#define MSR_PL0_SSP 0x000006a4
diff --git a/xen/include/public/arch-x86/cpufeatureset.h b/xen/include/public/arch-x86/cpufeatureset.h
index 2835688f1c..a2482c3627 100644
--- a/xen/include/public/arch-x86/cpufeatureset.h
+++ b/xen/include/public/arch-x86/cpufeatureset.h
@@ -252,6 +252,7 @@ XEN_CPUFEATURE(IBPB, 8*32+12) /*A IBPB support only (no IBRS, used by
/* Intel-defined CPU features, CPUID level 0x00000007:0.edx, word 9 */
XEN_CPUFEATURE(AVX512_4VNNIW, 9*32+ 2) /*A AVX512 Neural Network Instructions */
XEN_CPUFEATURE(AVX512_4FMAPS, 9*32+ 3) /*A AVX512 Multiply Accumulation Single Precision */
+XEN_CPUFEATURE(SRBDS_CTRL, 9*32+ 9) /* MSR_MCU_OPT_CTRL and RNGDS_MITG_DIS. */
XEN_CPUFEATURE(MD_CLEAR, 9*32+10) /*A VERW clears microarchitectural buffers */
XEN_CPUFEATURE(TSX_FORCE_ABORT, 9*32+13) /* MSR_TSX_FORCE_ABORT.RTM_ABORT */
XEN_CPUFEATURE(CET_IBT, 9*32+20) /* CET - Indirect Branch Tracking */

View file

@ -1,179 +0,0 @@
From: Andrew Cooper <andrew.cooper3@citrix.com>
Subject: x86/spec-ctrl: Mitigate the Special Register Buffer Data Sampling sidechannel
See patch documentation and comments.
This is part of XSA-320 / CVE-2020-0543
Signed-off-by: Andrew Cooper <andrew.cooper3@citrix.com>
Reviewed-by: Jan Beulich <jbeulich@suse.com>
diff --git a/docs/misc/xen-command-line.pandoc b/docs/misc/xen-command-line.pandoc
index 9268454297..c780312531 100644
--- a/docs/misc/xen-command-line.pandoc
+++ b/docs/misc/xen-command-line.pandoc
@@ -1991,7 +1991,7 @@ By default SSBD will be mitigated at runtime (i.e `ssbd=runtime`).
### spec-ctrl (x86)
> `= List of [ <bool>, xen=<bool>, {pv,hvm,msr-sc,rsb,md-clear}=<bool>,
> bti-thunk=retpoline|lfence|jmp, {ibrs,ibpb,ssbd,eager-fpu,
-> l1d-flush,branch-harden}=<bool> ]`
+> l1d-flush,branch-harden,srb-lock}=<bool> ]`
Controls for speculative execution sidechannel mitigations. By default, Xen
will pick the most appropriate mitigations based on compiled in support,
@@ -2068,6 +2068,12 @@ If Xen is compiled with `CONFIG_SPECULATIVE_HARDEN_BRANCH`, the
speculation barriers to protect selected conditional branches. By default,
Xen will enable this mitigation.
+On hardware supporting SRBDS_CTRL, the `srb-lock=` option can be used to force
+or prevent Xen from protect the Special Register Buffer from leaking stale
+data. By default, Xen will enable this mitigation, except on parts where MDS
+is fixed and TAA is fixed/mitigated (in which case, there is believed to be no
+way for an attacker to obtain the stale data).
+
### sync_console
> `= <boolean>`
diff --git a/xen/arch/x86/acpi/power.c b/xen/arch/x86/acpi/power.c
index feb0f6ce20..75c6e34164 100644
--- a/xen/arch/x86/acpi/power.c
+++ b/xen/arch/x86/acpi/power.c
@@ -295,6 +295,9 @@ static int enter_state(u32 state)
ci->spec_ctrl_flags |= (default_spec_ctrl_flags & SCF_ist_wrmsr);
spec_ctrl_exit_idle(ci);
+ if ( boot_cpu_has(X86_FEATURE_SRBDS_CTRL) )
+ wrmsrl(MSR_MCU_OPT_CTRL, default_xen_mcu_opt_ctrl);
+
done:
spin_debug_enable();
local_irq_restore(flags);
diff --git a/xen/arch/x86/smpboot.c b/xen/arch/x86/smpboot.c
index dc8fdac1a1..b1e51b3aff 100644
--- a/xen/arch/x86/smpboot.c
+++ b/xen/arch/x86/smpboot.c
@@ -361,12 +361,14 @@ void start_secondary(void *unused)
microcode_update_one(false);
/*
- * If MSR_SPEC_CTRL is available, apply Xen's default setting and discard
- * any firmware settings. Note: MSR_SPEC_CTRL may only become available
- * after loading microcode.
+ * If any speculative control MSRs are available, apply Xen's default
+ * settings. Note: These MSRs may only become available after loading
+ * microcode.
*/
if ( boot_cpu_has(X86_FEATURE_IBRSB) )
wrmsrl(MSR_SPEC_CTRL, default_xen_spec_ctrl);
+ if ( boot_cpu_has(X86_FEATURE_SRBDS_CTRL) )
+ wrmsrl(MSR_MCU_OPT_CTRL, default_xen_mcu_opt_ctrl);
tsx_init(); /* Needs microcode. May change HLE/RTM feature bits. */
diff --git a/xen/arch/x86/spec_ctrl.c b/xen/arch/x86/spec_ctrl.c
index 5fc1c6827e..33343062a7 100644
--- a/xen/arch/x86/spec_ctrl.c
+++ b/xen/arch/x86/spec_ctrl.c
@@ -65,6 +65,9 @@ static unsigned int __initdata l1d_maxphysaddr;
static bool __initdata cpu_has_bug_msbds_only; /* => minimal HT impact. */
static bool __initdata cpu_has_bug_mds; /* Any other M{LP,SB,FB}DS combination. */
+static int8_t __initdata opt_srb_lock = -1;
+uint64_t __read_mostly default_xen_mcu_opt_ctrl;
+
static int __init parse_spec_ctrl(const char *s)
{
const char *ss;
@@ -112,6 +115,7 @@ static int __init parse_spec_ctrl(const char *s)
opt_ssbd = false;
opt_l1d_flush = 0;
opt_branch_harden = false;
+ opt_srb_lock = 0;
}
else if ( val > 0 )
rc = -EINVAL;
@@ -178,6 +182,8 @@ static int __init parse_spec_ctrl(const char *s)
opt_l1d_flush = val;
else if ( (val = parse_boolean("branch-harden", s, ss)) >= 0 )
opt_branch_harden = val;
+ else if ( (val = parse_boolean("srb-lock", s, ss)) >= 0 )
+ opt_srb_lock = val;
else
rc = -EINVAL;
@@ -341,7 +347,7 @@ static void __init print_details(enum ind_thunk thunk, uint64_t caps)
"\n");
/* Settings for Xen's protection, irrespective of guests. */
- printk(" Xen settings: BTI-Thunk %s, SPEC_CTRL: %s%s%s, Other:%s%s%s%s\n",
+ printk(" Xen settings: BTI-Thunk %s, SPEC_CTRL: %s%s%s, Other:%s%s%s%s%s\n",
thunk == THUNK_NONE ? "N/A" :
thunk == THUNK_RETPOLINE ? "RETPOLINE" :
thunk == THUNK_LFENCE ? "LFENCE" :
@@ -352,6 +358,8 @@ static void __init print_details(enum ind_thunk thunk, uint64_t caps)
(default_xen_spec_ctrl & SPEC_CTRL_SSBD) ? " SSBD+" : " SSBD-",
!(caps & ARCH_CAPS_TSX_CTRL) ? "" :
(opt_tsx & 1) ? " TSX+" : " TSX-",
+ !boot_cpu_has(X86_FEATURE_SRBDS_CTRL) ? "" :
+ opt_srb_lock ? " SRB_LOCK+" : " SRB_LOCK-",
opt_ibpb ? " IBPB" : "",
opt_l1d_flush ? " L1D_FLUSH" : "",
opt_md_clear_pv || opt_md_clear_hvm ? " VERW" : "",
@@ -1149,6 +1157,34 @@ void __init init_speculation_mitigations(void)
tsx_init();
}
+ /* Calculate suitable defaults for MSR_MCU_OPT_CTRL */
+ if ( boot_cpu_has(X86_FEATURE_SRBDS_CTRL) )
+ {
+ uint64_t val;
+
+ rdmsrl(MSR_MCU_OPT_CTRL, val);
+
+ /*
+ * On some SRBDS-affected hardware, it may be safe to relax srb-lock
+ * by default.
+ *
+ * On parts which enumerate MDS_NO and not TAA_NO, TSX is the only way
+ * to access the Fill Buffer. If TSX isn't available (inc. SKU
+ * reasons on some models), or TSX is explicitly disabled, then there
+ * is no need for the extra overhead to protect RDRAND/RDSEED.
+ */
+ if ( opt_srb_lock == -1 &&
+ (caps & (ARCH_CAPS_MDS_NO|ARCH_CAPS_TAA_NO)) == ARCH_CAPS_MDS_NO &&
+ (!cpu_has_hle || ((caps & ARCH_CAPS_TSX_CTRL) && opt_tsx == 0)) )
+ opt_srb_lock = 0;
+
+ val &= ~MCU_OPT_CTRL_RNGDS_MITG_DIS;
+ if ( !opt_srb_lock )
+ val |= MCU_OPT_CTRL_RNGDS_MITG_DIS;
+
+ default_xen_mcu_opt_ctrl = val;
+ }
+
print_details(thunk, caps);
/*
@@ -1180,6 +1216,9 @@ void __init init_speculation_mitigations(void)
wrmsrl(MSR_SPEC_CTRL, bsp_delay_spec_ctrl ? 0 : default_xen_spec_ctrl);
}
+
+ if ( boot_cpu_has(X86_FEATURE_SRBDS_CTRL) )
+ wrmsrl(MSR_MCU_OPT_CTRL, default_xen_mcu_opt_ctrl);
}
static void __init __maybe_unused build_assertions(void)
diff --git a/xen/include/asm-x86/spec_ctrl.h b/xen/include/asm-x86/spec_ctrl.h
index 9caecddfec..b252bb8631 100644
--- a/xen/include/asm-x86/spec_ctrl.h
+++ b/xen/include/asm-x86/spec_ctrl.h
@@ -54,6 +54,8 @@ extern int8_t opt_pv_l1tf_hwdom, opt_pv_l1tf_domu;
*/
extern paddr_t l1tf_addr_mask, l1tf_safe_maddr;
+extern uint64_t default_xen_mcu_opt_ctrl;
+
static inline void init_shadow_spec_ctrl_state(void)
{
struct cpu_info *info = get_cpu_info();

View file

@ -1,31 +0,0 @@
From: Jan Beulich <jbeulich@suse.com>
Subject: vtd: improve IOMMU TLB flush
Do not limit PSI flushes to order 0 pages, in order to avoid doing a
full TLB flush if the passed in page has an order greater than 0 and
is aligned. Should increase the performance of IOMMU TLB flushes when
dealing with page orders greater than 0.
This is part of XSA-321.
Signed-off-by: Jan Beulich <jbeulich@suse.com>
--- a/xen/drivers/passthrough/vtd/iommu.c
+++ b/xen/drivers/passthrough/vtd/iommu.c
@@ -570,13 +570,14 @@ static int __must_check iommu_flush_iotl
if ( iommu_domid == -1 )
continue;
- if ( page_count != 1 || dfn_eq(dfn, INVALID_DFN) )
+ if ( !page_count || (page_count & (page_count - 1)) ||
+ dfn_eq(dfn, INVALID_DFN) || !IS_ALIGNED(dfn_x(dfn), page_count) )
rc = iommu_flush_iotlb_dsi(iommu, iommu_domid,
0, flush_dev_iotlb);
else
rc = iommu_flush_iotlb_psi(iommu, iommu_domid,
dfn_to_daddr(dfn),
- PAGE_ORDER_4K,
+ get_order_from_pages(page_count),
!dma_old_pte_present,
flush_dev_iotlb);

View file

@ -1,175 +0,0 @@
From: <security@xenproject.org>
Subject: vtd: prune (and rename) cache flush functions
Rename __iommu_flush_cache to iommu_sync_cache and remove
iommu_flush_cache_page. Also remove the iommu_flush_cache_entry
wrapper and just use iommu_sync_cache instead. Note the _entry suffix
was meaningless as the wrapper was already taking a size parameter in
bytes. While there also constify the addr parameter.
No functional change intended.
This is part of XSA-321.
Reviewed-by: Jan Beulich <jbeulich@suse.com>
--- a/xen/drivers/passthrough/vtd/extern.h
+++ b/xen/drivers/passthrough/vtd/extern.h
@@ -43,8 +43,7 @@ void disable_qinval(struct vtd_iommu *io
int enable_intremap(struct vtd_iommu *iommu, int eim);
void disable_intremap(struct vtd_iommu *iommu);
-void iommu_flush_cache_entry(void *addr, unsigned int size);
-void iommu_flush_cache_page(void *addr, unsigned long npages);
+void iommu_sync_cache(const void *addr, unsigned int size);
int iommu_alloc(struct acpi_drhd_unit *drhd);
void iommu_free(struct acpi_drhd_unit *drhd);
--- a/xen/drivers/passthrough/vtd/intremap.c
+++ b/xen/drivers/passthrough/vtd/intremap.c
@@ -230,7 +230,7 @@ static void free_remap_entry(struct vtd_
iremap_entries, iremap_entry);
update_irte(iommu, iremap_entry, &new_ire, false);
- iommu_flush_cache_entry(iremap_entry, sizeof(*iremap_entry));
+ iommu_sync_cache(iremap_entry, sizeof(*iremap_entry));
iommu_flush_iec_index(iommu, 0, index);
unmap_vtd_domain_page(iremap_entries);
@@ -406,7 +406,7 @@ static int ioapic_rte_to_remap_entry(str
}
update_irte(iommu, iremap_entry, &new_ire, !init);
- iommu_flush_cache_entry(iremap_entry, sizeof(*iremap_entry));
+ iommu_sync_cache(iremap_entry, sizeof(*iremap_entry));
iommu_flush_iec_index(iommu, 0, index);
unmap_vtd_domain_page(iremap_entries);
@@ -695,7 +695,7 @@ static int msi_msg_to_remap_entry(
update_irte(iommu, iremap_entry, &new_ire, msi_desc->irte_initialized);
msi_desc->irte_initialized = true;
- iommu_flush_cache_entry(iremap_entry, sizeof(*iremap_entry));
+ iommu_sync_cache(iremap_entry, sizeof(*iremap_entry));
iommu_flush_iec_index(iommu, 0, index);
unmap_vtd_domain_page(iremap_entries);
--- a/xen/drivers/passthrough/vtd/iommu.c
+++ b/xen/drivers/passthrough/vtd/iommu.c
@@ -140,7 +140,8 @@ static int context_get_domain_id(struct
}
static int iommus_incoherent;
-static void __iommu_flush_cache(void *addr, unsigned int size)
+
+void iommu_sync_cache(const void *addr, unsigned int size)
{
int i;
static unsigned int clflush_size = 0;
@@ -155,16 +156,6 @@ static void __iommu_flush_cache(void *ad
cacheline_flush((char *)addr + i);
}
-void iommu_flush_cache_entry(void *addr, unsigned int size)
-{
- __iommu_flush_cache(addr, size);
-}
-
-void iommu_flush_cache_page(void *addr, unsigned long npages)
-{
- __iommu_flush_cache(addr, PAGE_SIZE * npages);
-}
-
/* Allocate page table, return its machine address */
uint64_t alloc_pgtable_maddr(unsigned long npages, nodeid_t node)
{
@@ -183,7 +174,7 @@ uint64_t alloc_pgtable_maddr(unsigned lo
vaddr = __map_domain_page(cur_pg);
memset(vaddr, 0, PAGE_SIZE);
- iommu_flush_cache_page(vaddr, 1);
+ iommu_sync_cache(vaddr, PAGE_SIZE);
unmap_domain_page(vaddr);
cur_pg++;
}
@@ -216,7 +207,7 @@ static u64 bus_to_context_maddr(struct v
}
set_root_value(*root, maddr);
set_root_present(*root);
- iommu_flush_cache_entry(root, sizeof(struct root_entry));
+ iommu_sync_cache(root, sizeof(struct root_entry));
}
maddr = (u64) get_context_addr(*root);
unmap_vtd_domain_page(root_entries);
@@ -263,7 +254,7 @@ static u64 addr_to_dma_page_maddr(struct
*/
dma_set_pte_readable(*pte);
dma_set_pte_writable(*pte);
- iommu_flush_cache_entry(pte, sizeof(struct dma_pte));
+ iommu_sync_cache(pte, sizeof(struct dma_pte));
}
if ( level == 2 )
@@ -640,7 +631,7 @@ static int __must_check dma_pte_clear_on
*flush_flags |= IOMMU_FLUSHF_modified;
spin_unlock(&hd->arch.mapping_lock);
- iommu_flush_cache_entry(pte, sizeof(struct dma_pte));
+ iommu_sync_cache(pte, sizeof(struct dma_pte));
unmap_vtd_domain_page(page);
@@ -679,7 +670,7 @@ static void iommu_free_page_table(struct
iommu_free_pagetable(dma_pte_addr(*pte), next_level);
dma_clear_pte(*pte);
- iommu_flush_cache_entry(pte, sizeof(struct dma_pte));
+ iommu_sync_cache(pte, sizeof(struct dma_pte));
}
unmap_vtd_domain_page(pt_vaddr);
@@ -1400,7 +1391,7 @@ int domain_context_mapping_one(
context_set_address_width(*context, agaw);
context_set_fault_enable(*context);
context_set_present(*context);
- iommu_flush_cache_entry(context, sizeof(struct context_entry));
+ iommu_sync_cache(context, sizeof(struct context_entry));
spin_unlock(&iommu->lock);
/* Context entry was previously non-present (with domid 0). */
@@ -1564,7 +1555,7 @@ int domain_context_unmap_one(
context_clear_present(*context);
context_clear_entry(*context);
- iommu_flush_cache_entry(context, sizeof(struct context_entry));
+ iommu_sync_cache(context, sizeof(struct context_entry));
iommu_domid= domain_iommu_domid(domain, iommu);
if ( iommu_domid == -1 )
@@ -1791,7 +1782,7 @@ static int __must_check intel_iommu_map_
*pte = new;
- iommu_flush_cache_entry(pte, sizeof(struct dma_pte));
+ iommu_sync_cache(pte, sizeof(struct dma_pte));
spin_unlock(&hd->arch.mapping_lock);
unmap_vtd_domain_page(page);
@@ -1866,7 +1857,7 @@ int iommu_pte_flush(struct domain *d, ui
int iommu_domid;
int rc = 0;
- iommu_flush_cache_entry(pte, sizeof(struct dma_pte));
+ iommu_sync_cache(pte, sizeof(struct dma_pte));
for_each_drhd_unit ( drhd )
{
@@ -2724,7 +2715,7 @@ static int __init intel_iommu_quarantine
dma_set_pte_addr(*pte, maddr);
dma_set_pte_readable(*pte);
}
- iommu_flush_cache_page(parent, 1);
+ iommu_sync_cache(parent, PAGE_SIZE);
unmap_vtd_domain_page(parent);
parent = map_vtd_domain_page(maddr);

View file

@ -1,82 +0,0 @@
From: <security@xenproject.org>
Subject: x86/iommu: introduce a cache sync hook
The hook is only implemented for VT-d and it uses the already existing
iommu_sync_cache function present in VT-d code. The new hook is
added so that the cache can be flushed by code outside of VT-d when
using shared page tables.
Note that alloc_pgtable_maddr must use the now locally defined
sync_cache function, because IOMMU ops are not yet setup the first
time the function gets called during IOMMU initialization.
No functional change intended.
This is part of XSA-321.
Reviewed-by: Jan Beulich <jbeulich@suse.com>
--- a/xen/drivers/passthrough/vtd/extern.h
+++ b/xen/drivers/passthrough/vtd/extern.h
@@ -43,7 +43,6 @@ void disable_qinval(struct vtd_iommu *io
int enable_intremap(struct vtd_iommu *iommu, int eim);
void disable_intremap(struct vtd_iommu *iommu);
-void iommu_sync_cache(const void *addr, unsigned int size);
int iommu_alloc(struct acpi_drhd_unit *drhd);
void iommu_free(struct acpi_drhd_unit *drhd);
--- a/xen/drivers/passthrough/vtd/iommu.c
+++ b/xen/drivers/passthrough/vtd/iommu.c
@@ -141,7 +141,7 @@ static int context_get_domain_id(struct
static int iommus_incoherent;
-void iommu_sync_cache(const void *addr, unsigned int size)
+static void sync_cache(const void *addr, unsigned int size)
{
int i;
static unsigned int clflush_size = 0;
@@ -174,7 +174,7 @@ uint64_t alloc_pgtable_maddr(unsigned lo
vaddr = __map_domain_page(cur_pg);
memset(vaddr, 0, PAGE_SIZE);
- iommu_sync_cache(vaddr, PAGE_SIZE);
+ sync_cache(vaddr, PAGE_SIZE);
unmap_domain_page(vaddr);
cur_pg++;
}
@@ -2763,6 +2763,7 @@ const struct iommu_ops __initconstrel in
.iotlb_flush_all = iommu_flush_iotlb_all,
.get_reserved_device_memory = intel_iommu_get_reserved_device_memory,
.dump_p2m_table = vtd_dump_p2m_table,
+ .sync_cache = sync_cache,
};
const struct iommu_init_ops __initconstrel intel_iommu_init_ops = {
--- a/xen/include/asm-x86/iommu.h
+++ b/xen/include/asm-x86/iommu.h
@@ -121,6 +121,13 @@ extern bool untrusted_msi;
int pi_update_irte(const struct pi_desc *pi_desc, const struct pirq *pirq,
const uint8_t gvec);
+#define iommu_sync_cache(addr, size) ({ \
+ const struct iommu_ops *ops = iommu_get_ops(); \
+ \
+ if ( ops->sync_cache ) \
+ iommu_vcall(ops, sync_cache, addr, size); \
+})
+
#endif /* !__ARCH_X86_IOMMU_H__ */
/*
* Local variables:
--- a/xen/include/xen/iommu.h
+++ b/xen/include/xen/iommu.h
@@ -250,6 +250,7 @@ struct iommu_ops {
int (*setup_hpet_msi)(struct msi_desc *);
int (*adjust_irq_affinities)(void);
+ void (*sync_cache)(const void *addr, unsigned int size);
#endif /* CONFIG_X86 */
int __must_check (*suspend)(void);

View file

@ -1,36 +0,0 @@
From: <security@xenproject.org>
Subject: vtd: don't assume addresses are aligned in sync_cache
Current code in sync_cache assume that the address passed in is
aligned to a cache line size. Fix the code to support passing in
arbitrary addresses not necessarily aligned to a cache line size.
This is part of XSA-321.
Reviewed-by: Jan Beulich <jbeulich@suse.com>
--- a/xen/drivers/passthrough/vtd/iommu.c
+++ b/xen/drivers/passthrough/vtd/iommu.c
@@ -143,8 +143,8 @@ static int iommus_incoherent;
static void sync_cache(const void *addr, unsigned int size)
{
- int i;
- static unsigned int clflush_size = 0;
+ static unsigned long clflush_size = 0;
+ const void *end = addr + size;
if ( !iommus_incoherent )
return;
@@ -152,8 +152,9 @@ static void sync_cache(const void *addr,
if ( clflush_size == 0 )
clflush_size = get_cache_line_size();
- for ( i = 0; i < size; i += clflush_size )
- cacheline_flush((char *)addr + i);
+ addr -= (unsigned long)addr & (clflush_size - 1);
+ for ( ; addr < end; addr += clflush_size )
+ cacheline_flush((char *)addr);
}
/* Allocate page table, return its machine address */

View file

@ -1,24 +0,0 @@
From: <security@xenproject.org>
Subject: x86/alternative: introduce alternative_2
It's based on alternative_io_2 without inputs or outputs but with an
added memory clobber.
This is part of XSA-321.
Acked-by: Jan Beulich <jbeulich@suse.com>
--- a/xen/include/asm-x86/alternative.h
+++ b/xen/include/asm-x86/alternative.h
@@ -114,6 +114,11 @@ extern void alternative_branches(void);
#define alternative(oldinstr, newinstr, feature) \
asm volatile (ALTERNATIVE(oldinstr, newinstr, feature) : : : "memory")
+#define alternative_2(oldinstr, newinstr1, feature1, newinstr2, feature2) \
+ asm volatile (ALTERNATIVE_2(oldinstr, newinstr1, feature1, \
+ newinstr2, feature2) \
+ : : : "memory")
+
/*
* Alternative inline assembly with input.
*

View file

@ -1,91 +0,0 @@
From: <security@xenproject.org>
Subject: vtd: optimize CPU cache sync
Some VT-d IOMMUs are non-coherent, which requires a cache write back
in order for the changes made by the CPU to be visible to the IOMMU.
This cache write back was unconditionally done using clflush, but there are
other more efficient instructions to do so, hence implement support
for them using the alternative framework.
This is part of XSA-321.
Reviewed-by: Jan Beulich <jbeulich@suse.com>
--- a/xen/drivers/passthrough/vtd/extern.h
+++ b/xen/drivers/passthrough/vtd/extern.h
@@ -68,7 +68,6 @@ int __must_check qinval_device_iotlb_syn
u16 did, u16 size, u64 addr);
unsigned int get_cache_line_size(void);
-void cacheline_flush(char *);
void flush_all_cache(void);
uint64_t alloc_pgtable_maddr(unsigned long npages, nodeid_t node);
--- a/xen/drivers/passthrough/vtd/iommu.c
+++ b/xen/drivers/passthrough/vtd/iommu.c
@@ -31,6 +31,7 @@
#include <xen/pci_regs.h>
#include <xen/keyhandler.h>
#include <asm/msi.h>
+#include <asm/nops.h>
#include <asm/irq.h>
#include <asm/hvm/vmx/vmx.h>
#include <asm/p2m.h>
@@ -154,7 +155,42 @@ static void sync_cache(const void *addr,
addr -= (unsigned long)addr & (clflush_size - 1);
for ( ; addr < end; addr += clflush_size )
- cacheline_flush((char *)addr);
+/*
+ * The arguments to a macro must not include preprocessor directives. Doing so
+ * results in undefined behavior, so we have to create some defines here in
+ * order to avoid it.
+ */
+#if defined(HAVE_AS_CLWB)
+# define CLWB_ENCODING "clwb %[p]"
+#elif defined(HAVE_AS_XSAVEOPT)
+# define CLWB_ENCODING "data16 xsaveopt %[p]" /* clwb */
+#else
+# define CLWB_ENCODING ".byte 0x66, 0x0f, 0xae, 0x30" /* clwb (%%rax) */
+#endif
+
+#define BASE_INPUT(addr) [p] "m" (*(const char *)(addr))
+#if defined(HAVE_AS_CLWB) || defined(HAVE_AS_XSAVEOPT)
+# define INPUT BASE_INPUT
+#else
+# define INPUT(addr) "a" (addr), BASE_INPUT(addr)
+#endif
+ /*
+ * Note regarding the use of NOP_DS_PREFIX: it's faster to do a clflush
+ * + prefix than a clflush + nop, and hence the prefix is added instead
+ * of letting the alternative framework fill the gap by appending nops.
+ */
+ alternative_io_2(".byte " __stringify(NOP_DS_PREFIX) "; clflush %[p]",
+ "data16 clflush %[p]", /* clflushopt */
+ X86_FEATURE_CLFLUSHOPT,
+ CLWB_ENCODING,
+ X86_FEATURE_CLWB, /* no outputs */,
+ INPUT(addr));
+#undef INPUT
+#undef BASE_INPUT
+#undef CLWB_ENCODING
+
+ alternative_2("", "sfence", X86_FEATURE_CLFLUSHOPT,
+ "sfence", X86_FEATURE_CLWB);
}
/* Allocate page table, return its machine address */
--- a/xen/drivers/passthrough/vtd/x86/vtd.c
+++ b/xen/drivers/passthrough/vtd/x86/vtd.c
@@ -51,11 +51,6 @@ unsigned int get_cache_line_size(void)
return ((cpuid_ebx(1) >> 8) & 0xff) * 8;
}
-void cacheline_flush(char * addr)
-{
- clflush(addr);
-}
-
void flush_all_cache()
{
wbinvd();

View file

@ -1,153 +0,0 @@
From: <security@xenproject.org>
Subject: x86/ept: flush cache when modifying PTEs and sharing page tables
Modifications made to the page tables by EPT code need to be written
to memory when the page tables are shared with the IOMMU, as Intel
IOMMUs can be non-coherent and thus require changes to be written to
memory in order to be visible to the IOMMU.
In order to achieve this make sure data is written back to memory
after writing an EPT entry when the recalc bit is not set in
atomic_write_ept_entry. If such bit is set, the entry will be
adjusted and atomic_write_ept_entry will be called a second time
without the recalc bit set. Note that when splitting a super page the
new tables resulting of the split should also be written back.
Failure to do so can allow devices behind the IOMMU access to the
stale super page, or cause coherency issues as changes made by the
processor to the page tables are not visible to the IOMMU.
This allows to remove the VT-d specific iommu_pte_flush helper, since
the cache write back is now performed by atomic_write_ept_entry, and
hence iommu_iotlb_flush can be used to flush the IOMMU TLB. The newly
used method (iommu_iotlb_flush) can result in less flushes, since it
might sometimes be called rightly with 0 flags, in which case it
becomes a no-op.
This is part of XSA-321.
Reviewed-by: Jan Beulich <jbeulich@suse.com>
--- a/xen/arch/x86/mm/p2m-ept.c
+++ b/xen/arch/x86/mm/p2m-ept.c
@@ -58,6 +58,19 @@ static int atomic_write_ept_entry(struct
write_atomic(&entryptr->epte, new.epte);
+ /*
+ * The recalc field on the EPT is used to signal either that a
+ * recalculation of the EMT field is required (which doesn't effect the
+ * IOMMU), or a type change. Type changes can only be between ram_rw,
+ * logdirty and ioreq_server: changes to/from logdirty won't work well with
+ * an IOMMU anyway, as IOMMU #PFs are not synchronous and will lead to
+ * aborts, and changes to/from ioreq_server are already fully flushed
+ * before returning to guest context (see
+ * XEN_DMOP_map_mem_type_to_ioreq_server).
+ */
+ if ( !new.recalc && iommu_use_hap_pt(p2m->domain) )
+ iommu_sync_cache(entryptr, sizeof(*entryptr));
+
return 0;
}
@@ -278,6 +291,9 @@ static bool_t ept_split_super_page(struc
break;
}
+ if ( iommu_use_hap_pt(p2m->domain) )
+ iommu_sync_cache(table, EPT_PAGETABLE_ENTRIES * sizeof(ept_entry_t));
+
unmap_domain_page(table);
/* Even failed we should install the newly allocated ept page. */
@@ -337,6 +353,9 @@ static int ept_next_level(struct p2m_dom
if ( !next )
return GUEST_TABLE_MAP_FAILED;
+ if ( iommu_use_hap_pt(p2m->domain) )
+ iommu_sync_cache(next, EPT_PAGETABLE_ENTRIES * sizeof(ept_entry_t));
+
rc = atomic_write_ept_entry(p2m, ept_entry, e, next_level);
ASSERT(rc == 0);
}
@@ -821,7 +840,10 @@ out:
need_modify_vtd_table )
{
if ( iommu_use_hap_pt(d) )
- rc = iommu_pte_flush(d, gfn, &ept_entry->epte, order, vtd_pte_present);
+ rc = iommu_iotlb_flush(d, _dfn(gfn), (1u << order),
+ (iommu_flags ? IOMMU_FLUSHF_added : 0) |
+ (vtd_pte_present ? IOMMU_FLUSHF_modified
+ : 0));
else if ( need_iommu_pt_sync(d) )
rc = iommu_flags ?
iommu_legacy_map(d, _dfn(gfn), mfn, order, iommu_flags) :
--- a/xen/drivers/passthrough/vtd/iommu.c
+++ b/xen/drivers/passthrough/vtd/iommu.c
@@ -1884,53 +1884,6 @@ static int intel_iommu_lookup_page(struc
return 0;
}
-int iommu_pte_flush(struct domain *d, uint64_t dfn, uint64_t *pte,
- int order, int present)
-{
- struct acpi_drhd_unit *drhd;
- struct vtd_iommu *iommu = NULL;
- struct domain_iommu *hd = dom_iommu(d);
- bool_t flush_dev_iotlb;
- int iommu_domid;
- int rc = 0;
-
- iommu_sync_cache(pte, sizeof(struct dma_pte));
-
- for_each_drhd_unit ( drhd )
- {
- iommu = drhd->iommu;
- if ( !test_bit(iommu->index, &hd->arch.iommu_bitmap) )
- continue;
-
- flush_dev_iotlb = !!find_ats_dev_drhd(iommu);
- iommu_domid= domain_iommu_domid(d, iommu);
- if ( iommu_domid == -1 )
- continue;
-
- rc = iommu_flush_iotlb_psi(iommu, iommu_domid,
- __dfn_to_daddr(dfn),
- order, !present, flush_dev_iotlb);
- if ( rc > 0 )
- {
- iommu_flush_write_buffer(iommu);
- rc = 0;
- }
- }
-
- if ( unlikely(rc) )
- {
- if ( !d->is_shutting_down && printk_ratelimit() )
- printk(XENLOG_ERR VTDPREFIX
- " d%d: IOMMU pages flush failed: %d\n",
- d->domain_id, rc);
-
- if ( !is_hardware_domain(d) )
- domain_crash(d);
- }
-
- return rc;
-}
-
static int __init vtd_ept_page_compatible(struct vtd_iommu *iommu)
{
u64 ept_cap, vtd_cap = iommu->cap;
--- a/xen/include/asm-x86/iommu.h
+++ b/xen/include/asm-x86/iommu.h
@@ -97,10 +97,6 @@ static inline int iommu_adjust_irq_affin
: 0;
}
-/* While VT-d specific, this must get declared in a generic header. */
-int __must_check iommu_pte_flush(struct domain *d, u64 gfn, u64 *pte,
- int order, int present);
-
static inline bool iommu_supports_x2apic(void)
{
return iommu_init_ops && iommu_init_ops->supports_x2apic

View file

@ -1,63 +0,0 @@
From 030300ebbb86c40c12db038714479d746167c767 Mon Sep 17 00:00:00 2001
From: Julien Grall <jgrall@amazon.com>
Date: Tue, 26 May 2020 18:31:33 +0100
Subject: [PATCH] xen: Check the alignment of the offset pased via
VCPUOP_register_vcpu_info
Currently a guest is able to register any guest physical address to use
for the vcpu_info structure as long as the structure can fits in the
rest of the frame.
This means a guest can provide an address that is not aligned to the
natural alignment of the structure.
On Arm 32-bit, unaligned access are completely forbidden by the
hypervisor. This will result to a data abort which is fatal.
On Arm 64-bit, unaligned access are only forbidden when used for atomic
access. As the structure contains fields (such as evtchn_pending_self)
that are updated using atomic operations, any unaligned access will be
fatal as well.
While the misalignment is only fatal on Arm, a generic check is added
as an x86 guest shouldn't sensibly pass an unaligned address (this
would result to a split lock).
This is XSA-327.
Reported-by: Julien Grall <jgrall@amazon.com>
Signed-off-by: Julien Grall <jgrall@amazon.com>
Reviewed-by: Andrew Cooper <andrew.cooper3@citrix.com>
Reviewed-by: Stefano Stabellini <sstabellini@kernel.org>
---
xen/common/domain.c | 10 ++++++++++
1 file changed, 10 insertions(+)
diff --git a/xen/common/domain.c b/xen/common/domain.c
index 7cc9526139a6..e9be05f1d05f 100644
--- a/xen/common/domain.c
+++ b/xen/common/domain.c
@@ -1227,10 +1227,20 @@ int map_vcpu_info(struct vcpu *v, unsigned long gfn, unsigned offset)
void *mapping;
vcpu_info_t *new_info;
struct page_info *page;
+ unsigned int align;
if ( offset > (PAGE_SIZE - sizeof(vcpu_info_t)) )
return -EINVAL;
+#ifdef CONFIG_COMPAT
+ if ( has_32bit_shinfo(d) )
+ align = alignof(new_info->compat);
+ else
+#endif
+ align = alignof(*new_info);
+ if ( offset & (align - 1) )
+ return -EINVAL;
+
if ( !mfn_eq(v->vcpu_info_mfn, INVALID_MFN) )
return -EINVAL;
--
2.17.1

View file

@ -1,118 +0,0 @@
From: Jan Beulich <jbeulich@suse.com>
Subject: x86/EPT: ept_set_middle_entry() related adjustments
ept_split_super_page() wants to further modify the newly allocated
table, so have ept_set_middle_entry() return the mapped pointer rather
than tearing it down and then getting re-established right again.
Similarly ept_next_level() wants to hand back a mapped pointer of
the next level page, so re-use the one established by
ept_set_middle_entry() in case that path was taken.
Pull the setting of suppress_ve ahead of insertion into the higher level
table, and don't have ept_split_super_page() set the field a 2nd time.
This is part of XSA-328.
Signed-off-by: Jan Beulich <jbeulich@suse.com>
--- a/xen/arch/x86/mm/p2m-ept.c
+++ b/xen/arch/x86/mm/p2m-ept.c
@@ -187,8 +187,9 @@ static void ept_p2m_type_to_flags(struct
#define GUEST_TABLE_SUPER_PAGE 2
#define GUEST_TABLE_POD_PAGE 3
-/* Fill in middle levels of ept table */
-static int ept_set_middle_entry(struct p2m_domain *p2m, ept_entry_t *ept_entry)
+/* Fill in middle level of ept table; return pointer to mapped new table. */
+static ept_entry_t *ept_set_middle_entry(struct p2m_domain *p2m,
+ ept_entry_t *ept_entry)
{
mfn_t mfn;
ept_entry_t *table;
@@ -196,7 +197,12 @@ static int ept_set_middle_entry(struct p
mfn = p2m_alloc_ptp(p2m, 0);
if ( mfn_eq(mfn, INVALID_MFN) )
- return 0;
+ return NULL;
+
+ table = map_domain_page(mfn);
+
+ for ( i = 0; i < EPT_PAGETABLE_ENTRIES; i++ )
+ table[i].suppress_ve = 1;
ept_entry->epte = 0;
ept_entry->mfn = mfn_x(mfn);
@@ -208,14 +214,7 @@ static int ept_set_middle_entry(struct p
ept_entry->suppress_ve = 1;
- table = map_domain_page(mfn);
-
- for ( i = 0; i < EPT_PAGETABLE_ENTRIES; i++ )
- table[i].suppress_ve = 1;
-
- unmap_domain_page(table);
-
- return 1;
+ return table;
}
/* free ept sub tree behind an entry */
@@ -253,10 +252,10 @@ static bool_t ept_split_super_page(struc
ASSERT(is_epte_superpage(ept_entry));
- if ( !ept_set_middle_entry(p2m, &new_ept) )
+ table = ept_set_middle_entry(p2m, &new_ept);
+ if ( !table )
return 0;
- table = map_domain_page(_mfn(new_ept.mfn));
trunk = 1UL << ((level - 1) * EPT_TABLE_ORDER);
for ( i = 0; i < EPT_PAGETABLE_ENTRIES; i++ )
@@ -267,7 +266,6 @@ static bool_t ept_split_super_page(struc
epte->sp = (level > 1);
epte->mfn += i * trunk;
epte->snp = is_iommu_enabled(p2m->domain) && iommu_snoop;
- epte->suppress_ve = 1;
ept_p2m_type_to_flags(p2m, epte, epte->sa_p2mt, epte->access);
@@ -306,8 +304,7 @@ static int ept_next_level(struct p2m_dom
ept_entry_t **table, unsigned long *gfn_remainder,
int next_level)
{
- unsigned long mfn;
- ept_entry_t *ept_entry, e;
+ ept_entry_t *ept_entry, *next = NULL, e;
u32 shift, index;
shift = next_level * EPT_TABLE_ORDER;
@@ -332,19 +329,17 @@ static int ept_next_level(struct p2m_dom
if ( read_only )
return GUEST_TABLE_MAP_FAILED;
- if ( !ept_set_middle_entry(p2m, ept_entry) )
+ next = ept_set_middle_entry(p2m, ept_entry);
+ if ( !next )
return GUEST_TABLE_MAP_FAILED;
- else
- e = atomic_read_ept_entry(ept_entry); /* Refresh */
+ /* e is now stale and hence may not be used anymore below. */
}
-
/* The only time sp would be set here is if we had hit a superpage */
- if ( is_epte_superpage(&e) )
+ else if ( is_epte_superpage(&e) )
return GUEST_TABLE_SUPER_PAGE;
- mfn = e.mfn;
unmap_domain_page(*table);
- *table = map_domain_page(_mfn(mfn));
+ *table = next ?: map_domain_page(_mfn(e.mfn));
*gfn_remainder &= (1UL << shift) - 1;
return GUEST_TABLE_NORMAL_PAGE;
}

View file

@ -1,48 +0,0 @@
From: <security@xenproject.org>
Subject: x86/ept: atomically modify entries in ept_next_level
ept_next_level was passing a live PTE pointer to ept_set_middle_entry,
which was then modified without taking into account that the PTE could
be part of a live EPT table. This wasn't a security issue because the
pages returned by p2m_alloc_ptp are zeroed, so adding such an entry
before actually initializing it didn't allow a guest to access
physical memory addresses it wasn't supposed to access.
This is part of XSA-328.
Reviewed-by: Jan Beulich <jbeulich@suse.com>
--- a/xen/arch/x86/mm/p2m-ept.c
+++ b/xen/arch/x86/mm/p2m-ept.c
@@ -307,6 +307,8 @@ static int ept_next_level(struct p2m_dom
ept_entry_t *ept_entry, *next = NULL, e;
u32 shift, index;
+ ASSERT(next_level);
+
shift = next_level * EPT_TABLE_ORDER;
index = *gfn_remainder >> shift;
@@ -323,16 +325,20 @@ static int ept_next_level(struct p2m_dom
if ( !is_epte_present(&e) )
{
+ int rc;
+
if ( e.sa_p2mt == p2m_populate_on_demand )
return GUEST_TABLE_POD_PAGE;
if ( read_only )
return GUEST_TABLE_MAP_FAILED;
- next = ept_set_middle_entry(p2m, ept_entry);
+ next = ept_set_middle_entry(p2m, &e);
if ( !next )
return GUEST_TABLE_MAP_FAILED;
- /* e is now stale and hence may not be used anymore below. */
+
+ rc = atomic_write_ept_entry(p2m, ept_entry, e, next_level);
+ ASSERT(rc == 0);
}
/* The only time sp would be set here is if we had hit a superpage */
else if ( is_epte_superpage(&e) )

22
xsa363.patch Normal file
View file

@ -0,0 +1,22 @@
From: Jan Beulich <jbeulich@suse.com>
Subject: SUPPORT.md: PV display frontend is unsupported in "backend allocation" mode
This wasn't meant to be supported, but wasn't stated this way.
This is XSA-363.
Reported-by: Jan Belich <jbeulich@suse.com>
Signed-off-by: Jan Beulich <jbeulich@suse.com>
--- a/SUPPORT.md
+++ b/SUPPORT.md
@@ -414,7 +414,8 @@ Guest-side driver capable of speaking th
Guest-side driver capable of speaking the Xen PV display protocol
- Status, Linux: Supported
+ Status, Linux: Supported (outside of "backend allocation" mode)
+ Status, Linux: Experimental (in "backend allocation" mode)
### PV Console (frontend)

9214
zstd-dom0.patch Normal file

File diff suppressed because it is too large Load diff