aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDaniel Néri <dne+alpine@mayonnaise.net>2020-07-11 00:19:26 +0200
committerDaniel Néri <dne+alpine@mayonnaise.net>2020-07-11 12:25:29 +0200
commit054ec5f5456be1d95d13e7b5c5607e9c0ed5904d (patch)
treed4d6805248a066a766c719250ca2fb3abf75472e
parent60d20906e7d32ccfc9aae3542c72aa3169c1bdc3 (diff)
downloadaports-054ec5f5456be1d95d13e7b5c5607e9c0ed5904d.tar.gz
aports-054ec5f5456be1d95d13e7b5c5607e9c0ed5904d.tar.bz2
aports-054ec5f5456be1d95d13e7b5c5607e9c0ed5904d.tar.xz
main/xen: security fixes for XSA-317, XSA-319, XSA-321, XSA-327 and XSA-328
-rw-r--r--main/xen/APKBUILD32
-rw-r--r--main/xen/xsa317.patch50
-rw-r--r--main/xen/xsa319.patch27
-rw-r--r--main/xen/xsa321-4.13-1.patch31
-rw-r--r--main/xen/xsa321-4.13-2.patch175
-rw-r--r--main/xen/xsa321-4.13-3.patch82
-rw-r--r--main/xen/xsa321-4.13-4.patch36
-rw-r--r--main/xen/xsa321-4.13-5.patch24
-rw-r--r--main/xen/xsa321-4.13-6.patch91
-rw-r--r--main/xen/xsa321-4.13-7.patch153
-rw-r--r--main/xen/xsa327.patch63
-rw-r--r--main/xen/xsa328-4.13-1.patch118
-rw-r--r--main/xen/xsa328-4.13-2.patch48
13 files changed, 929 insertions, 1 deletions
diff --git a/main/xen/APKBUILD b/main/xen/APKBUILD
index 34a77db71d..e4ecde8dab 100644
--- a/main/xen/APKBUILD
+++ b/main/xen/APKBUILD
@@ -2,7 +2,7 @@
# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
pkgname=xen
pkgver=4.13.1
-pkgrel=1
+pkgrel=2
pkgdesc="Xen hypervisor"
url="https://www.xenproject.org/"
arch="x86_64 armhf aarch64" # enable armv7 when builds with gcc8
@@ -170,6 +170,12 @@ options="!strip"
# - CVE-????-????? XSA-312
# 4.13.1-r1:
# - CVE-2020-0543 XSA-320
+# 4.13.1-r2:
+# - CVE-2020-15566 XSA-317
+# - CVE-2020-15563 XSA-319
+# - CVE-2020-15565 XSA-321
+# - CVE-2020-15564 XSA-327
+# - CVE-2020-15567 XSA-328
case "$CARCH" in
x86*)
@@ -235,6 +241,18 @@ source="https://downloads.xenproject.org/release/xen/$pkgver/xen-$pkgver.tar.gz
xsa320-4.13-1.patch
xsa320-4.13-2.patch
+ xsa317.patch
+ xsa319.patch
+ xsa328-4.13-1.patch
+ xsa328-4.13-2.patch
+ xsa321-4.13-1.patch
+ xsa321-4.13-2.patch
+ xsa321-4.13-3.patch
+ xsa321-4.13-4.patch
+ xsa321-4.13-5.patch
+ xsa321-4.13-6.patch
+ xsa321-4.13-7.patch
+ xsa327.patch
xenstored.initd
xenstored.confd
@@ -481,8 +499,20 @@ e76816c6ad0e91dc5f81947f266da3429b20e6d976c3e8c41202c6179532eec878a3f0913921ef3a
8c9cfc6afca325df1d8026e21ed03fa8cd2c7e1a21a56cc1968301c5ab634bfe849951899e75d328951d7a41273d1e49a2448edbadec0029ed410c43c0549812 hotplug-Linux-iscsi-block-handle-lun-1.patch
61f66bab603778fb41bfe8e85320c15f2bf3e5d8583e077b56a93784dbdb9b2c7c5e55ce18f06b87501429086f8410d102d3ed5f2a77d54bcfa328bc07681f4d drop-test.py.patch
8cb12dbfc05a53898a97d47d71ab6b8a6f81c5e5579fd765b37303faea95c645cb8dedc05e3d064bdf070e93814e00bf8939767acc1127513375bab0fe2f4436 py3-compat.patch
+325f66b008a76ff569fdca430e2926633996511f1bd7dcd375259377e4c88758b13c95ee66b8edaa5ffebc3d927442409dc36bd8e35b2c928e43d82a539583cf xsa317.patch
+d57d8cfd749df1816060345bedd9fa7ef2381ea9d85562ddf0c39ffe832ca56834c3e8c1fb67a64fd5631fd219c4d66a3ef655dca0989bf39911c87e0145717f xsa319.patch
be3b2ece73ba625024fd9c85eda0fb04b60dab3533a78a1d768783e242b0d81e4af5b91cfb85245be89d37f26807f3e846054c1e4518d208e4f7768b05a80ba0 xsa320-4.13-1.patch
91ae9b5fb7ba950aa508b2e3fdd1c1618fea3a3d51affc232e4880d6c12d9056bc595a34843d70c7fba8b2ec5f856a97b1dec60bcc4abdf9240df1643fe2184a xsa320-4.13-2.patch
+05e23669ce04a6d03a159310756a0d2b71b3abb8b24cffd3a58c84bca1ca8597f293c31945d08a2b95a75dcbd013c9bdd89ba2682433c7d42f4765615d097b45 xsa321-4.13-1.patch
+8bae6927a462160c46976f5425cc4c51b6788d86b52ad8cccee576c0f3783ec6af4059365191030909372d8aa229001127c4aeba95d480422a781550657df2da xsa321-4.13-2.patch
+0c8e3371e0cc17b1e785cc98d888e6871ad8551c4486afc8450bc56444347a3168700fc77a508d0a2b9545e21aac107bb1ff3cf17be358f45e0bb895806ad14f xsa321-4.13-3.patch
+7ebbb7e1a647aa209aa7303964050d29aa4e2c39a4dcd1f5b64d51d20812323b95e48906161f410a46a11a5b94d06c5a6d25551a8d837bf2d099604646870a72 xsa321-4.13-4.patch
+90a2ca8bbbac8f82f934ab3bf4bbdc61d23ff87e3d8154d71b794e84df65b81b26b13bd95cc9a66912c98566f33993ab4f222d99756feccdf3309b3e255e2856 xsa321-4.13-5.patch
+d7edad538e74d27d877e6393b6a98cd7df44d405d9b99534c16a3e7eee60193b53a1fa983cd90700ea8ffaf74e444327bf92ffb432591ceb963e028ae57c1e8f xsa321-4.13-6.patch
+061a6ad3c01de21bb980fd11df38c4f9d4e48288f1a2f28bcbd82c2b01ce85e65c2b3103a84f2f95c87af50ee6344a1c0850f533528f6a32aa0961780f2b0a5a xsa321-4.13-7.patch
+83823056dbd0142585d8b0fb9b3179ac8cc099a21ee489008a4cfb1f310daae72dff1fb6c7cd3a1c8ca5cec43a6b964587d8121a2423226baad0bcd302e73263 xsa327.patch
+14699f43d8ef857c3ddf17d95a80cfe4234a50349e0220a110c2046a63873037686ddbd3cd06ad708a4a76148fe0b812179e46431f04abb8ac7ae01c37b8cf2b xsa328-4.13-1.patch
+a9551daa73a7deb332fcfd647d0df6ebab84699a91eaca43697e182612304910610f80c1edc3c5e3b86e4a580137a4ae178fadba62fe148795a6ab240df174cf xsa328-4.13-2.patch
52c43beb2596d645934d0f909f2d21f7587b6898ed5e5e7046799a8ed6d58f7a09c5809e1634fa26152f3fd4f3e7cfa07da7076f01b4a20cc8f5df8b9cb77e50 xenstored.initd
093f7fbd43faf0a16a226486a0776bade5dc1681d281c5946a3191c32d74f9699c6bf5d0ab8de9d1195a2461165d1660788e92a3156c9b3c7054d7b2d52d7ff0 xenstored.confd
3c86ed48fbee0af4051c65c4a3893f131fa66e47bf083caf20c9b6aa4b63fdead8832f84a58d0e27964bc49ec8397251b34e5be5c212c139f556916dc8da9523 xenconsoled.initd
diff --git a/main/xen/xsa317.patch b/main/xen/xsa317.patch
new file mode 100644
index 0000000000..20e2c643d0
--- /dev/null
+++ b/main/xen/xsa317.patch
@@ -0,0 +1,50 @@
+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
+
diff --git a/main/xen/xsa319.patch b/main/xen/xsa319.patch
new file mode 100644
index 0000000000..769443c900
--- /dev/null
+++ b/main/xen/xsa319.patch
@@ -0,0 +1,27 @@
+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);
diff --git a/main/xen/xsa321-4.13-1.patch b/main/xen/xsa321-4.13-1.patch
new file mode 100644
index 0000000000..9a08ab240e
--- /dev/null
+++ b/main/xen/xsa321-4.13-1.patch
@@ -0,0 +1,31 @@
+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);
+
diff --git a/main/xen/xsa321-4.13-2.patch b/main/xen/xsa321-4.13-2.patch
new file mode 100644
index 0000000000..1e48615f2b
--- /dev/null
+++ b/main/xen/xsa321-4.13-2.patch
@@ -0,0 +1,175 @@
+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);
diff --git a/main/xen/xsa321-4.13-3.patch b/main/xen/xsa321-4.13-3.patch
new file mode 100644
index 0000000000..c141c4b785
--- /dev/null
+++ b/main/xen/xsa321-4.13-3.patch
@@ -0,0 +1,82 @@
+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);
diff --git a/main/xen/xsa321-4.13-4.patch b/main/xen/xsa321-4.13-4.patch
new file mode 100644
index 0000000000..62bbcc7271
--- /dev/null
+++ b/main/xen/xsa321-4.13-4.patch
@@ -0,0 +1,36 @@
+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 */
diff --git a/main/xen/xsa321-4.13-5.patch b/main/xen/xsa321-4.13-5.patch
new file mode 100644
index 0000000000..60cfe6ccdf
--- /dev/null
+++ b/main/xen/xsa321-4.13-5.patch
@@ -0,0 +1,24 @@
+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.
+ *
diff --git a/main/xen/xsa321-4.13-6.patch b/main/xen/xsa321-4.13-6.patch
new file mode 100644
index 0000000000..4c5c5ab0ba
--- /dev/null
+++ b/main/xen/xsa321-4.13-6.patch
@@ -0,0 +1,91 @@
+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();
diff --git a/main/xen/xsa321-4.13-7.patch b/main/xen/xsa321-4.13-7.patch
new file mode 100644
index 0000000000..0bd018f972
--- /dev/null
+++ b/main/xen/xsa321-4.13-7.patch
@@ -0,0 +1,153 @@
+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
diff --git a/main/xen/xsa327.patch b/main/xen/xsa327.patch
new file mode 100644
index 0000000000..0541cfa0df
--- /dev/null
+++ b/main/xen/xsa327.patch
@@ -0,0 +1,63 @@
+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
+
diff --git a/main/xen/xsa328-4.13-1.patch b/main/xen/xsa328-4.13-1.patch
new file mode 100644
index 0000000000..56e48de3e9
--- /dev/null
+++ b/main/xen/xsa328-4.13-1.patch
@@ -0,0 +1,118 @@
+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;
+ }
diff --git a/main/xen/xsa328-4.13-2.patch b/main/xen/xsa328-4.13-2.patch
new file mode 100644
index 0000000000..c4f437f625
--- /dev/null
+++ b/main/xen/xsa328-4.13-2.patch
@@ -0,0 +1,48 @@
+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) )