arm-fix-co-processor-register-typo.patch
arm-do-not-use-nocrossrefs-directive-with-ld.lld.patch
arm-fix-build-warning-in-proc-v7-bugs.c.patch
+xen-xenbus-don-t-let-xenbus_grant_ring-remove-grants-in-error-case.patch
+xen-grant-table-add-gnttab_try_end_foreign_access.patch
+xen-blkfront-don-t-use-gnttab_query_foreign_access-for-mapped-status.patch
+xen-netfront-don-t-use-gnttab_query_foreign_access-for-mapped-status.patch
+xen-scsifront-don-t-use-gnttab_query_foreign_access-for-mapped-status.patch
+xen-gntalloc-don-t-use-gnttab_query_foreign_access.patch
+xen-remove-gnttab_query_foreign_access.patch
+xen-9p-use-alloc-free_pages_exact.patch
+xen-gnttab-fix-gnttab_end_foreign_access-without-page-specified.patch
+xen-netfront-react-properly-to-failing-gnttab_end_foreign_access_ref.patch
--- /dev/null
+From foo@baz Thu Mar 10 02:39:42 PM CET 2022
+From: Juergen Gross <jgross@suse.com>
+Date: Fri, 25 Feb 2022 16:05:42 +0100
+Subject: xen/9p: use alloc/free_pages_exact()
+
+From: Juergen Gross <jgross@suse.com>
+
+Commit 5cadd4bb1d7fc9ab201ac14620d1a478357e4ebd upstream.
+
+Instead of __get_free_pages() and free_pages() use alloc_pages_exact()
+and free_pages_exact(). This is in preparation of a change of
+gnttab_end_foreign_access() which will prohibit use of high-order
+pages.
+
+By using the local variable "order" instead of ring->intf->ring_order
+in the error path of xen_9pfs_front_alloc_dataring() another bug is
+fixed, as the error path can be entered before ring->intf->ring_order
+is being set.
+
+By using alloc_pages_exact() the size in bytes is specified for the
+allocation, which fixes another bug for the case of
+order < (PAGE_SHIFT - XEN_PAGE_SHIFT).
+
+This is part of CVE-2022-23041 / XSA-396.
+
+Reported-by: Simon Gaiser <simon@invisiblethingslab.com>
+Signed-off-by: Juergen Gross <jgross@suse.com>
+Reviewed-by: Jan Beulich <jbeulich@suse.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ net/9p/trans_xen.c | 14 ++++++--------
+ 1 file changed, 6 insertions(+), 8 deletions(-)
+
+--- a/net/9p/trans_xen.c
++++ b/net/9p/trans_xen.c
+@@ -301,9 +301,9 @@ static void xen_9pfs_front_free(struct x
+ ref = priv->rings[i].intf->ref[j];
+ gnttab_end_foreign_access(ref, 0, 0);
+ }
+- free_pages((unsigned long)priv->rings[i].data.in,
+- XEN_9PFS_RING_ORDER -
+- (PAGE_SHIFT - XEN_PAGE_SHIFT));
++ free_pages_exact(priv->rings[i].data.in,
++ 1UL << (XEN_9PFS_RING_ORDER +
++ XEN_PAGE_SHIFT));
+ }
+ gnttab_end_foreign_access(priv->rings[i].ref, 0, 0);
+ free_page((unsigned long)priv->rings[i].intf);
+@@ -341,8 +341,8 @@ static int xen_9pfs_front_alloc_dataring
+ if (ret < 0)
+ goto out;
+ ring->ref = ret;
+- bytes = (void *)__get_free_pages(GFP_KERNEL | __GFP_ZERO,
+- XEN_9PFS_RING_ORDER - (PAGE_SHIFT - XEN_PAGE_SHIFT));
++ bytes = alloc_pages_exact(1UL << (XEN_9PFS_RING_ORDER + XEN_PAGE_SHIFT),
++ GFP_KERNEL | __GFP_ZERO);
+ if (!bytes) {
+ ret = -ENOMEM;
+ goto out;
+@@ -373,9 +373,7 @@ out:
+ if (bytes) {
+ for (i--; i >= 0; i--)
+ gnttab_end_foreign_access(ring->intf->ref[i], 0, 0);
+- free_pages((unsigned long)bytes,
+- XEN_9PFS_RING_ORDER -
+- (PAGE_SHIFT - XEN_PAGE_SHIFT));
++ free_pages_exact(bytes, 1UL << (XEN_9PFS_RING_ORDER + XEN_PAGE_SHIFT));
+ }
+ gnttab_end_foreign_access(ring->ref, 0, 0);
+ free_page((unsigned long)ring->intf);
--- /dev/null
+From foo@baz Thu Mar 10 02:39:42 PM CET 2022
+From: Juergen Gross <jgross@suse.com>
+Date: Fri, 25 Feb 2022 16:05:41 +0100
+Subject: xen/blkfront: don't use gnttab_query_foreign_access() for mapped status
+
+From: Juergen Gross <jgross@suse.com>
+
+Commit abf1fd5919d6238ee3bc5eb4a9b6c3947caa6638 upstream.
+
+It isn't enough to check whether a grant is still being in use by
+calling gnttab_query_foreign_access(), as a mapping could be realized
+by the other side just after having called that function.
+
+In case the call was done in preparation of revoking a grant it is
+better to do so via gnttab_end_foreign_access_ref() and check the
+success of that operation instead.
+
+For the ring allocation use alloc_pages_exact() in order to avoid
+high order pages in case of a multi-page ring.
+
+If a grant wasn't unmapped by the backend without persistent grants
+being used, set the device state to "error".
+
+This is CVE-2022-23036 / part of XSA-396.
+
+Reported-by: Demi Marie Obenour <demi@invisiblethingslab.com>
+Signed-off-by: Juergen Gross <jgross@suse.com>
+Reviewed-by: Roger Pau Monné <roger.pau@citrix.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/block/xen-blkfront.c | 67 +++++++++++++++++++++++++------------------
+ 1 file changed, 39 insertions(+), 28 deletions(-)
+
+--- a/drivers/block/xen-blkfront.c
++++ b/drivers/block/xen-blkfront.c
+@@ -1278,17 +1278,16 @@ static void blkif_free_ring(struct blkfr
+ list_for_each_entry_safe(persistent_gnt, n,
+ &rinfo->grants, node) {
+ list_del(&persistent_gnt->node);
+- if (persistent_gnt->gref != GRANT_INVALID_REF) {
+- gnttab_end_foreign_access(persistent_gnt->gref,
+- 0, 0UL);
+- rinfo->persistent_gnts_c--;
+- }
++ if (persistent_gnt->gref == GRANT_INVALID_REF ||
++ !gnttab_try_end_foreign_access(persistent_gnt->gref))
++ continue;
++
++ rinfo->persistent_gnts_c--;
+ if (info->feature_persistent)
+ __free_page(persistent_gnt->page);
+ kfree(persistent_gnt);
+ }
+ }
+- BUG_ON(rinfo->persistent_gnts_c != 0);
+
+ for (i = 0; i < BLK_RING_SIZE(info); i++) {
+ /*
+@@ -1345,7 +1344,8 @@ free_shadow:
+ rinfo->ring_ref[i] = GRANT_INVALID_REF;
+ }
+ }
+- free_pages((unsigned long)rinfo->ring.sring, get_order(info->nr_ring_pages * XEN_PAGE_SIZE));
++ free_pages_exact(rinfo->ring.sring,
++ info->nr_ring_pages * XEN_PAGE_SIZE);
+ rinfo->ring.sring = NULL;
+
+ if (rinfo->irq)
+@@ -1429,9 +1429,15 @@ static int blkif_get_final_status(enum b
+ return BLKIF_RSP_OKAY;
+ }
+
+-static bool blkif_completion(unsigned long *id,
+- struct blkfront_ring_info *rinfo,
+- struct blkif_response *bret)
++/*
++ * Return values:
++ * 1 response processed.
++ * 0 missing further responses.
++ * -1 error while processing.
++ */
++static int blkif_completion(unsigned long *id,
++ struct blkfront_ring_info *rinfo,
++ struct blkif_response *bret)
+ {
+ int i = 0;
+ struct scatterlist *sg;
+@@ -1505,42 +1511,43 @@ static bool blkif_completion(unsigned lo
+ }
+ /* Add the persistent grant into the list of free grants */
+ for (i = 0; i < num_grant; i++) {
+- if (gnttab_query_foreign_access(s->grants_used[i]->gref)) {
++ if (!gnttab_try_end_foreign_access(s->grants_used[i]->gref)) {
+ /*
+ * If the grant is still mapped by the backend (the
+ * backend has chosen to make this grant persistent)
+ * we add it at the head of the list, so it will be
+ * reused first.
+ */
+- if (!info->feature_persistent)
+- pr_alert_ratelimited("backed has not unmapped grant: %u\n",
+- s->grants_used[i]->gref);
++ if (!info->feature_persistent) {
++ pr_alert("backed has not unmapped grant: %u\n",
++ s->grants_used[i]->gref);
++ return -1;
++ }
+ list_add(&s->grants_used[i]->node, &rinfo->grants);
+ rinfo->persistent_gnts_c++;
+ } else {
+ /*
+- * If the grant is not mapped by the backend we end the
+- * foreign access and add it to the tail of the list,
+- * so it will not be picked again unless we run out of
+- * persistent grants.
++ * If the grant is not mapped by the backend we add it
++ * to the tail of the list, so it will not be picked
++ * again unless we run out of persistent grants.
+ */
+- gnttab_end_foreign_access(s->grants_used[i]->gref, 0, 0UL);
+ s->grants_used[i]->gref = GRANT_INVALID_REF;
+ list_add_tail(&s->grants_used[i]->node, &rinfo->grants);
+ }
+ }
+ if (s->req.operation == BLKIF_OP_INDIRECT) {
+ for (i = 0; i < INDIRECT_GREFS(num_grant); i++) {
+- if (gnttab_query_foreign_access(s->indirect_grants[i]->gref)) {
+- if (!info->feature_persistent)
+- pr_alert_ratelimited("backed has not unmapped grant: %u\n",
+- s->indirect_grants[i]->gref);
++ if (!gnttab_try_end_foreign_access(s->indirect_grants[i]->gref)) {
++ if (!info->feature_persistent) {
++ pr_alert("backed has not unmapped grant: %u\n",
++ s->indirect_grants[i]->gref);
++ return -1;
++ }
+ list_add(&s->indirect_grants[i]->node, &rinfo->grants);
+ rinfo->persistent_gnts_c++;
+ } else {
+ struct page *indirect_page;
+
+- gnttab_end_foreign_access(s->indirect_grants[i]->gref, 0, 0UL);
+ /*
+ * Add the used indirect page back to the list of
+ * available pages for indirect grefs.
+@@ -1621,12 +1628,17 @@ static irqreturn_t blkif_interrupt(int i
+ }
+
+ if (bret.operation != BLKIF_OP_DISCARD) {
++ int ret;
++
+ /*
+ * We may need to wait for an extra response if the
+ * I/O request is split in 2
+ */
+- if (!blkif_completion(&id, rinfo, &bret))
++ ret = blkif_completion(&id, rinfo, &bret);
++ if (!ret)
+ continue;
++ if (unlikely(ret < 0))
++ goto err;
+ }
+
+ if (add_id_to_freelist(rinfo, id)) {
+@@ -1732,8 +1744,7 @@ static int setup_blkring(struct xenbus_d
+ for (i = 0; i < info->nr_ring_pages; i++)
+ rinfo->ring_ref[i] = GRANT_INVALID_REF;
+
+- sring = (struct blkif_sring *)__get_free_pages(GFP_NOIO | __GFP_HIGH,
+- get_order(ring_size));
++ sring = alloc_pages_exact(ring_size, GFP_NOIO);
+ if (!sring) {
+ xenbus_dev_fatal(dev, -ENOMEM, "allocating shared ring");
+ return -ENOMEM;
+@@ -1743,7 +1754,7 @@ static int setup_blkring(struct xenbus_d
+
+ err = xenbus_grant_ring(dev, rinfo->ring.sring, info->nr_ring_pages, gref);
+ if (err < 0) {
+- free_pages((unsigned long)sring, get_order(ring_size));
++ free_pages_exact(sring, ring_size);
+ rinfo->ring.sring = NULL;
+ goto fail;
+ }
--- /dev/null
+From foo@baz Thu Mar 10 02:39:42 PM CET 2022
+From: Juergen Gross <jgross@suse.com>
+Date: Fri, 25 Feb 2022 16:05:42 +0100
+Subject: xen/gntalloc: don't use gnttab_query_foreign_access()
+
+From: Juergen Gross <jgross@suse.com>
+
+Commit d3b6372c5881cb54925212abb62c521df8ba4809 upstream.
+
+Using gnttab_query_foreign_access() is unsafe, as it is racy by design.
+
+The use case in the gntalloc driver is not needed at all. While at it
+replace the call of gnttab_end_foreign_access_ref() with a call of
+gnttab_end_foreign_access(), which is what is really wanted there. In
+case the grant wasn't used due to an allocation failure, just free the
+grant via gnttab_free_grant_reference().
+
+This is CVE-2022-23039 / part of XSA-396.
+
+Reported-by: Demi Marie Obenour <demi@invisiblethingslab.com>
+Signed-off-by: Juergen Gross <jgross@suse.com>
+Reviewed-by: Jan Beulich <jbeulich@suse.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/xen/gntalloc.c | 25 +++++++------------------
+ 1 file changed, 7 insertions(+), 18 deletions(-)
+
+--- a/drivers/xen/gntalloc.c
++++ b/drivers/xen/gntalloc.c
+@@ -169,20 +169,14 @@ undo:
+ __del_gref(gref);
+ }
+
+- /* It's possible for the target domain to map the just-allocated grant
+- * references by blindly guessing their IDs; if this is done, then
+- * __del_gref will leave them in the queue_gref list. They need to be
+- * added to the global list so that we can free them when they are no
+- * longer referenced.
+- */
+- if (unlikely(!list_empty(&queue_gref)))
+- list_splice_tail(&queue_gref, &gref_list);
+ mutex_unlock(&gref_mutex);
+ return rc;
+ }
+
+ static void __del_gref(struct gntalloc_gref *gref)
+ {
++ unsigned long addr;
++
+ if (gref->notify.flags & UNMAP_NOTIFY_CLEAR_BYTE) {
+ uint8_t *tmp = kmap(gref->page);
+ tmp[gref->notify.pgoff] = 0;
+@@ -196,21 +190,16 @@ static void __del_gref(struct gntalloc_g
+ gref->notify.flags = 0;
+
+ if (gref->gref_id) {
+- if (gnttab_query_foreign_access(gref->gref_id))
+- return;
+-
+- if (!gnttab_end_foreign_access_ref(gref->gref_id, 0))
+- return;
+-
+- gnttab_free_grant_reference(gref->gref_id);
++ if (gref->page) {
++ addr = (unsigned long)page_to_virt(gref->page);
++ gnttab_end_foreign_access(gref->gref_id, 0, addr);
++ } else
++ gnttab_free_grant_reference(gref->gref_id);
+ }
+
+ gref_size--;
+ list_del(&gref->next_gref);
+
+- if (gref->page)
+- __free_page(gref->page);
+-
+ kfree(gref);
+ }
+
--- /dev/null
+From foo@baz Thu Mar 10 02:39:42 PM CET 2022
+From: Juergen Gross <jgross@suse.com>
+Date: Fri, 25 Feb 2022 16:05:43 +0100
+Subject: xen/gnttab: fix gnttab_end_foreign_access() without page specified
+
+From: Juergen Gross <jgross@suse.com>
+
+Commit 42baefac638f06314298087394b982ead9ec444b upstream.
+
+gnttab_end_foreign_access() is used to free a grant reference and
+optionally to free the associated page. In case the grant is still in
+use by the other side processing is being deferred. This leads to a
+problem in case no page to be freed is specified by the caller: the
+caller doesn't know that the page is still mapped by the other side
+and thus should not be used for other purposes.
+
+The correct way to handle this situation is to take an additional
+reference to the granted page in case handling is being deferred and
+to drop that reference when the grant reference could be freed
+finally.
+
+This requires that there are no users of gnttab_end_foreign_access()
+left directly repurposing the granted page after the call, as this
+might result in clobbered data or information leaks via the not yet
+freed grant reference.
+
+This is part of CVE-2022-23041 / XSA-396.
+
+Reported-by: Simon Gaiser <simon@invisiblethingslab.com>
+Signed-off-by: Juergen Gross <jgross@suse.com>
+Reviewed-by: Jan Beulich <jbeulich@suse.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/xen/grant-table.c | 30 +++++++++++++++++++++++-------
+ include/xen/grant_table.h | 7 ++++++-
+ 2 files changed, 29 insertions(+), 8 deletions(-)
+
+--- a/drivers/xen/grant-table.c
++++ b/drivers/xen/grant-table.c
+@@ -114,6 +114,10 @@ struct gnttab_ops {
+ * return the frame.
+ */
+ unsigned long (*end_foreign_transfer_ref)(grant_ref_t ref);
++ /*
++ * Read the frame number related to a given grant reference.
++ */
++ unsigned long (*read_frame)(grant_ref_t ref);
+ };
+
+ struct unmap_refs_callback_data {
+@@ -278,6 +282,11 @@ int gnttab_end_foreign_access_ref(grant_
+ }
+ EXPORT_SYMBOL_GPL(gnttab_end_foreign_access_ref);
+
++static unsigned long gnttab_read_frame_v1(grant_ref_t ref)
++{
++ return gnttab_shared.v1[ref].frame;
++}
++
+ struct deferred_entry {
+ struct list_head list;
+ grant_ref_t ref;
+@@ -307,12 +316,9 @@ static void gnttab_handle_deferred(unsig
+ spin_unlock_irqrestore(&gnttab_list_lock, flags);
+ if (_gnttab_end_foreign_access_ref(entry->ref, entry->ro)) {
+ put_free_entry(entry->ref);
+- if (entry->page) {
+- pr_debug("freeing g.e. %#x (pfn %#lx)\n",
+- entry->ref, page_to_pfn(entry->page));
+- put_page(entry->page);
+- } else
+- pr_info("freeing g.e. %#x\n", entry->ref);
++ pr_debug("freeing g.e. %#x (pfn %#lx)\n",
++ entry->ref, page_to_pfn(entry->page));
++ put_page(entry->page);
+ kfree(entry);
+ entry = NULL;
+ } else {
+@@ -337,9 +343,18 @@ static void gnttab_handle_deferred(unsig
+ static void gnttab_add_deferred(grant_ref_t ref, bool readonly,
+ struct page *page)
+ {
+- struct deferred_entry *entry = kmalloc(sizeof(*entry), GFP_ATOMIC);
++ struct deferred_entry *entry;
++ gfp_t gfp = (in_atomic() || irqs_disabled()) ? GFP_ATOMIC : GFP_KERNEL;
+ const char *what = KERN_WARNING "leaking";
+
++ entry = kmalloc(sizeof(*entry), gfp);
++ if (!page) {
++ unsigned long gfn = gnttab_interface->read_frame(ref);
++
++ page = pfn_to_page(gfn_to_pfn(gfn));
++ get_page(page);
++ }
++
+ if (entry) {
+ unsigned long flags;
+
+@@ -1011,6 +1026,7 @@ static const struct gnttab_ops gnttab_v1
+ .update_entry = gnttab_update_entry_v1,
+ .end_foreign_access_ref = gnttab_end_foreign_access_ref_v1,
+ .end_foreign_transfer_ref = gnttab_end_foreign_transfer_ref_v1,
++ .read_frame = gnttab_read_frame_v1,
+ };
+
+ static void gnttab_request_version(void)
+--- a/include/xen/grant_table.h
++++ b/include/xen/grant_table.h
+@@ -100,7 +100,12 @@ int gnttab_end_foreign_access_ref(grant_
+ * Note that the granted page might still be accessed (read or write) by the
+ * other side after gnttab_end_foreign_access() returns, so even if page was
+ * specified as 0 it is not allowed to just reuse the page for other
+- * purposes immediately.
++ * purposes immediately. gnttab_end_foreign_access() will take an additional
++ * reference to the granted page in this case, which is dropped only after
++ * the grant is no longer in use.
++ * This requires that multi page allocations for areas subject to
++ * gnttab_end_foreign_access() are done via alloc_pages_exact() (and freeing
++ * via free_pages_exact()) in order to avoid high order pages.
+ */
+ void gnttab_end_foreign_access(grant_ref_t ref, int readonly,
+ unsigned long page);
--- /dev/null
+From foo@baz Thu Mar 10 02:39:42 PM CET 2022
+From: Juergen Gross <jgross@suse.com>
+Date: Fri, 25 Feb 2022 16:05:41 +0100
+Subject: xen/grant-table: add gnttab_try_end_foreign_access()
+
+From: Juergen Gross <jgross@suse.com>
+
+Commit 6b1775f26a2da2b05a6dc8ec2b5d14e9a4701a1a upstream.
+
+Add a new grant table function gnttab_try_end_foreign_access(), which
+will remove and free a grant if it is not in use.
+
+Its main use case is to either free a grant if it is no longer in use,
+or to take some other action if it is still in use. This other action
+can be an error exit, or (e.g. in the case of blkfront persistent grant
+feature) some special handling.
+
+This is CVE-2022-23036, CVE-2022-23038 / part of XSA-396.
+
+Reported-by: Demi Marie Obenour <demi@invisiblethingslab.com>
+Signed-off-by: Juergen Gross <jgross@suse.com>
+Reviewed-by: Jan Beulich <jbeulich@suse.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/xen/grant-table.c | 14 ++++++++++++--
+ include/xen/grant_table.h | 12 ++++++++++++
+ 2 files changed, 24 insertions(+), 2 deletions(-)
+
+--- a/drivers/xen/grant-table.c
++++ b/drivers/xen/grant-table.c
+@@ -378,11 +378,21 @@ static void gnttab_add_deferred(grant_re
+ what, ref, page ? page_to_pfn(page) : -1);
+ }
+
++int gnttab_try_end_foreign_access(grant_ref_t ref)
++{
++ int ret = _gnttab_end_foreign_access_ref(ref, 0);
++
++ if (ret)
++ put_free_entry(ref);
++
++ return ret;
++}
++EXPORT_SYMBOL_GPL(gnttab_try_end_foreign_access);
++
+ void gnttab_end_foreign_access(grant_ref_t ref, int readonly,
+ unsigned long page)
+ {
+- if (gnttab_end_foreign_access_ref(ref, readonly)) {
+- put_free_entry(ref);
++ if (gnttab_try_end_foreign_access(ref)) {
+ if (page != 0)
+ put_page(virt_to_page(page));
+ } else
+--- a/include/xen/grant_table.h
++++ b/include/xen/grant_table.h
+@@ -97,10 +97,22 @@ int gnttab_end_foreign_access_ref(grant_
+ * access has been ended, free the given page too. Access will be ended
+ * immediately iff the grant entry is not in use, otherwise it will happen
+ * some time later. page may be 0, in which case no freeing will occur.
++ * Note that the granted page might still be accessed (read or write) by the
++ * other side after gnttab_end_foreign_access() returns, so even if page was
++ * specified as 0 it is not allowed to just reuse the page for other
++ * purposes immediately.
+ */
+ void gnttab_end_foreign_access(grant_ref_t ref, int readonly,
+ unsigned long page);
+
++/*
++ * End access through the given grant reference, iff the grant entry is
++ * no longer in use. In case of success ending foreign access, the
++ * grant reference is deallocated.
++ * Return 1 if the grant entry was freed, 0 if it is still in use.
++ */
++int gnttab_try_end_foreign_access(grant_ref_t ref);
++
+ int gnttab_grant_foreign_transfer(domid_t domid, unsigned long pfn);
+
+ unsigned long gnttab_end_foreign_transfer_ref(grant_ref_t ref);
--- /dev/null
+From foo@baz Thu Mar 10 02:39:42 PM CET 2022
+From: Juergen Gross <jgross@suse.com>
+Date: Fri, 25 Feb 2022 16:05:41 +0100
+Subject: xen/netfront: don't use gnttab_query_foreign_access() for mapped status
+
+From: Juergen Gross <jgross@suse.com>
+
+Commit 31185df7e2b1d2fa1de4900247a12d7b9c7087eb upstream.
+
+It isn't enough to check whether a grant is still being in use by
+calling gnttab_query_foreign_access(), as a mapping could be realized
+by the other side just after having called that function.
+
+In case the call was done in preparation of revoking a grant it is
+better to do so via gnttab_end_foreign_access_ref() and check the
+success of that operation instead.
+
+This is CVE-2022-23037 / part of XSA-396.
+
+Reported-by: Demi Marie Obenour <demi@invisiblethingslab.com>
+Signed-off-by: Juergen Gross <jgross@suse.com>
+Reviewed-by: Jan Beulich <jbeulich@suse.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/net/xen-netfront.c | 6 ++----
+ 1 file changed, 2 insertions(+), 4 deletions(-)
+
+--- a/drivers/net/xen-netfront.c
++++ b/drivers/net/xen-netfront.c
+@@ -414,14 +414,12 @@ static bool xennet_tx_buf_gc(struct netf
+ queue->tx_link[id] = TX_LINK_NONE;
+ skb = queue->tx_skbs[id];
+ queue->tx_skbs[id] = NULL;
+- if (unlikely(gnttab_query_foreign_access(
+- queue->grant_tx_ref[id]) != 0)) {
++ if (unlikely(!gnttab_end_foreign_access_ref(
++ queue->grant_tx_ref[id], GNTMAP_readonly))) {
+ dev_alert(dev,
+ "Grant still in use by backend domain\n");
+ goto err;
+ }
+- gnttab_end_foreign_access_ref(
+- queue->grant_tx_ref[id], GNTMAP_readonly);
+ gnttab_release_grant_reference(
+ &queue->gref_tx_head, queue->grant_tx_ref[id]);
+ queue->grant_tx_ref[id] = GRANT_INVALID_REF;
--- /dev/null
+From foo@baz Thu Mar 10 02:39:42 PM CET 2022
+From: Juergen Gross <jgross@suse.com>
+Date: Fri, 25 Feb 2022 16:05:43 +0100
+Subject: xen/netfront: react properly to failing gnttab_end_foreign_access_ref()
+
+From: Juergen Gross <jgross@suse.com>
+
+Commit 66e3531b33ee51dad17c463b4d9c9f52e341503d upstream.
+
+When calling gnttab_end_foreign_access_ref() the returned value must
+be tested and the reaction to that value should be appropriate.
+
+In case of failure in xennet_get_responses() the reaction should not be
+to crash the system, but to disable the network device.
+
+The calls in setup_netfront() can be replaced by calls of
+gnttab_end_foreign_access(). While at it avoid double free of ring
+pages and grant references via xennet_disconnect_backend() in this case.
+
+This is CVE-2022-23042 / part of XSA-396.
+
+Reported-by: Demi Marie Obenour <demi@invisiblethingslab.com>
+Signed-off-by: Juergen Gross <jgross@suse.com>
+Reviewed-by: Jan Beulich <jbeulich@suse.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/net/xen-netfront.c | 48 +++++++++++++++++++++++++++++----------------
+ 1 file changed, 31 insertions(+), 17 deletions(-)
+
+--- a/drivers/net/xen-netfront.c
++++ b/drivers/net/xen-netfront.c
+@@ -839,7 +839,6 @@ static int xennet_get_responses(struct n
+ int max = XEN_NETIF_NR_SLOTS_MIN + (rx->status <= RX_COPY_THRESHOLD);
+ int slots = 1;
+ int err = 0;
+- unsigned long ret;
+
+ if (rx->flags & XEN_NETRXF_extra_info) {
+ err = xennet_get_extras(queue, extras, rp);
+@@ -870,8 +869,13 @@ static int xennet_get_responses(struct n
+ goto next;
+ }
+
+- ret = gnttab_end_foreign_access_ref(ref, 0);
+- BUG_ON(!ret);
++ if (!gnttab_end_foreign_access_ref(ref, 0)) {
++ dev_alert(dev,
++ "Grant still in use by backend domain\n");
++ queue->info->broken = true;
++ dev_alert(dev, "Disabled for further use\n");
++ return -EINVAL;
++ }
+
+ gnttab_release_grant_reference(&queue->gref_rx_head, ref);
+
+@@ -1075,6 +1079,10 @@ static int xennet_poll(struct napi_struc
+ err = xennet_get_responses(queue, &rinfo, rp, &tmpq);
+
+ if (unlikely(err)) {
++ if (queue->info->broken) {
++ spin_unlock(&queue->rx_lock);
++ return 0;
++ }
+ err:
+ while ((skb = __skb_dequeue(&tmpq)))
+ __skb_queue_tail(&errq, skb);
+@@ -1652,7 +1660,7 @@ static int setup_netfront(struct xenbus_
+ struct netfront_queue *queue, unsigned int feature_split_evtchn)
+ {
+ struct xen_netif_tx_sring *txs;
+- struct xen_netif_rx_sring *rxs;
++ struct xen_netif_rx_sring *rxs = NULL;
+ grant_ref_t gref;
+ int err;
+
+@@ -1672,21 +1680,21 @@ static int setup_netfront(struct xenbus_
+
+ err = xenbus_grant_ring(dev, txs, 1, &gref);
+ if (err < 0)
+- goto grant_tx_ring_fail;
++ goto fail;
+ queue->tx_ring_ref = gref;
+
+ rxs = (struct xen_netif_rx_sring *)get_zeroed_page(GFP_NOIO | __GFP_HIGH);
+ if (!rxs) {
+ err = -ENOMEM;
+ xenbus_dev_fatal(dev, err, "allocating rx ring page");
+- goto alloc_rx_ring_fail;
++ goto fail;
+ }
+ SHARED_RING_INIT(rxs);
+ FRONT_RING_INIT(&queue->rx, rxs, XEN_PAGE_SIZE);
+
+ err = xenbus_grant_ring(dev, rxs, 1, &gref);
+ if (err < 0)
+- goto grant_rx_ring_fail;
++ goto fail;
+ queue->rx_ring_ref = gref;
+
+ if (feature_split_evtchn)
+@@ -1699,22 +1707,28 @@ static int setup_netfront(struct xenbus_
+ err = setup_netfront_single(queue);
+
+ if (err)
+- goto alloc_evtchn_fail;
++ goto fail;
+
+ return 0;
+
+ /* If we fail to setup netfront, it is safe to just revoke access to
+ * granted pages because backend is not accessing it at this point.
+ */
+-alloc_evtchn_fail:
+- gnttab_end_foreign_access_ref(queue->rx_ring_ref, 0);
+-grant_rx_ring_fail:
+- free_page((unsigned long)rxs);
+-alloc_rx_ring_fail:
+- gnttab_end_foreign_access_ref(queue->tx_ring_ref, 0);
+-grant_tx_ring_fail:
+- free_page((unsigned long)txs);
+-fail:
++ fail:
++ if (queue->rx_ring_ref != GRANT_INVALID_REF) {
++ gnttab_end_foreign_access(queue->rx_ring_ref, 0,
++ (unsigned long)rxs);
++ queue->rx_ring_ref = GRANT_INVALID_REF;
++ } else {
++ free_page((unsigned long)rxs);
++ }
++ if (queue->tx_ring_ref != GRANT_INVALID_REF) {
++ gnttab_end_foreign_access(queue->tx_ring_ref, 0,
++ (unsigned long)txs);
++ queue->tx_ring_ref = GRANT_INVALID_REF;
++ } else {
++ free_page((unsigned long)txs);
++ }
+ return err;
+ }
+
--- /dev/null
+From foo@baz Thu Mar 10 02:39:42 PM CET 2022
+From: Juergen Gross <jgross@suse.com>
+Date: Fri, 25 Feb 2022 16:05:42 +0100
+Subject: xen: remove gnttab_query_foreign_access()
+
+From: Juergen Gross <jgross@suse.com>
+
+Commit 1dbd11ca75fe664d3e54607547771d021f531f59 upstream.
+
+Remove gnttab_query_foreign_access(), as it is unused and unsafe to
+use.
+
+All previous use cases assumed a grant would not be in use after
+gnttab_query_foreign_access() returned 0. This information is useless
+in best case, as it only refers to a situation in the past, which could
+have changed already.
+
+Signed-off-by: Juergen Gross <jgross@suse.com>
+Reviewed-by: Jan Beulich <jbeulich@suse.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/xen/grant-table.c | 19 -------------------
+ include/xen/grant_table.h | 2 --
+ 2 files changed, 21 deletions(-)
+
+--- a/drivers/xen/grant-table.c
++++ b/drivers/xen/grant-table.c
+@@ -114,13 +114,6 @@ struct gnttab_ops {
+ * return the frame.
+ */
+ unsigned long (*end_foreign_transfer_ref)(grant_ref_t ref);
+- /*
+- * Query the status of a grant entry. Ref parameter is reference of
+- * queried grant entry, return value is the status of queried entry.
+- * Detailed status(writing/reading) can be gotten from the return value
+- * by bit operations.
+- */
+- int (*query_foreign_access)(grant_ref_t ref);
+ };
+
+ struct unmap_refs_callback_data {
+@@ -255,17 +248,6 @@ int gnttab_grant_foreign_access(domid_t
+ }
+ EXPORT_SYMBOL_GPL(gnttab_grant_foreign_access);
+
+-static int gnttab_query_foreign_access_v1(grant_ref_t ref)
+-{
+- return gnttab_shared.v1[ref].flags & (GTF_reading|GTF_writing);
+-}
+-
+-int gnttab_query_foreign_access(grant_ref_t ref)
+-{
+- return gnttab_interface->query_foreign_access(ref);
+-}
+-EXPORT_SYMBOL_GPL(gnttab_query_foreign_access);
+-
+ static int gnttab_end_foreign_access_ref_v1(grant_ref_t ref, int readonly)
+ {
+ u16 flags, nflags;
+@@ -1029,7 +1011,6 @@ static const struct gnttab_ops gnttab_v1
+ .update_entry = gnttab_update_entry_v1,
+ .end_foreign_access_ref = gnttab_end_foreign_access_ref_v1,
+ .end_foreign_transfer_ref = gnttab_end_foreign_transfer_ref_v1,
+- .query_foreign_access = gnttab_query_foreign_access_v1,
+ };
+
+ static void gnttab_request_version(void)
+--- a/include/xen/grant_table.h
++++ b/include/xen/grant_table.h
+@@ -118,8 +118,6 @@ int gnttab_grant_foreign_transfer(domid_
+ unsigned long gnttab_end_foreign_transfer_ref(grant_ref_t ref);
+ unsigned long gnttab_end_foreign_transfer(grant_ref_t ref);
+
+-int gnttab_query_foreign_access(grant_ref_t ref);
+-
+ /*
+ * operations on reserved batches of grant references
+ */
--- /dev/null
+From foo@baz Thu Mar 10 02:39:42 PM CET 2022
+From: Juergen Gross <jgross@suse.com>
+Date: Fri, 25 Feb 2022 16:05:42 +0100
+Subject: xen/scsifront: don't use gnttab_query_foreign_access() for mapped status
+
+From: Juergen Gross <jgross@suse.com>
+
+Commit 33172ab50a53578a95691310f49567c9266968b0 upstream.
+
+It isn't enough to check whether a grant is still being in use by
+calling gnttab_query_foreign_access(), as a mapping could be realized
+by the other side just after having called that function.
+
+In case the call was done in preparation of revoking a grant it is
+better to do so via gnttab_try_end_foreign_access() and check the
+success of that operation instead.
+
+This is CVE-2022-23038 / part of XSA-396.
+
+Reported-by: Demi Marie Obenour <demi@invisiblethingslab.com>
+Signed-off-by: Juergen Gross <jgross@suse.com>
+Reviewed-by: Jan Beulich <jbeulich@suse.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/scsi/xen-scsifront.c | 3 +--
+ 1 file changed, 1 insertion(+), 2 deletions(-)
+
+--- a/drivers/scsi/xen-scsifront.c
++++ b/drivers/scsi/xen-scsifront.c
+@@ -233,12 +233,11 @@ static void scsifront_gnttab_done(struct
+ return;
+
+ for (i = 0; i < shadow->nr_grants; i++) {
+- if (unlikely(gnttab_query_foreign_access(shadow->gref[i]))) {
++ if (unlikely(!gnttab_try_end_foreign_access(shadow->gref[i]))) {
+ shost_printk(KERN_ALERT, info->host, KBUILD_MODNAME
+ "grant still in use by backend\n");
+ BUG();
+ }
+- gnttab_end_foreign_access(shadow->gref[i], 0, 0UL);
+ }
+
+ kfree(shadow->sg);
--- /dev/null
+From foo@baz Thu Mar 10 02:39:42 PM CET 2022
+From: Juergen Gross <jgross@suse.com>
+Date: Fri, 25 Feb 2022 16:05:40 +0100
+Subject: xen/xenbus: don't let xenbus_grant_ring() remove grants in error case
+
+From: Juergen Gross <jgross@suse.com>
+
+Commit 3777ea7bac3113005b7180e6b9dadf16d19a5827 upstream.
+
+Letting xenbus_grant_ring() tear down grants in the error case is
+problematic, as the other side could already have used these grants.
+Calling gnttab_end_foreign_access_ref() without checking success is
+resulting in an unclear situation for any caller of xenbus_grant_ring()
+as in the error case the memory pages of the ring page might be
+partially mapped. Freeing them would risk unwanted foreign access to
+them, while not freeing them would leak memory.
+
+In order to remove the need to undo any gnttab_grant_foreign_access()
+calls, use gnttab_alloc_grant_references() to make sure no further
+error can occur in the loop granting access to the ring pages.
+
+It should be noted that this way of handling removes leaking of
+grant entries in the error case, too.
+
+This is CVE-2022-23040 / part of XSA-396.
+
+Reported-by: Demi Marie Obenour <demi@invisiblethingslab.com>
+Signed-off-by: Juergen Gross <jgross@suse.com>
+Reviewed-by: Jan Beulich <jbeulich@suse.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/xen/xenbus/xenbus_client.c | 24 +++++++++++-------------
+ 1 file changed, 11 insertions(+), 13 deletions(-)
+
+--- a/drivers/xen/xenbus/xenbus_client.c
++++ b/drivers/xen/xenbus/xenbus_client.c
+@@ -368,7 +368,14 @@ int xenbus_grant_ring(struct xenbus_devi
+ unsigned int nr_pages, grant_ref_t *grefs)
+ {
+ int err;
+- int i, j;
++ unsigned int i;
++ grant_ref_t gref_head;
++
++ err = gnttab_alloc_grant_references(nr_pages, &gref_head);
++ if (err) {
++ xenbus_dev_fatal(dev, err, "granting access to ring page");
++ return err;
++ }
+
+ for (i = 0; i < nr_pages; i++) {
+ unsigned long gfn;
+@@ -378,23 +385,14 @@ int xenbus_grant_ring(struct xenbus_devi
+ else
+ gfn = virt_to_gfn(vaddr);
+
+- err = gnttab_grant_foreign_access(dev->otherend_id, gfn, 0);
+- if (err < 0) {
+- xenbus_dev_fatal(dev, err,
+- "granting access to ring page");
+- goto fail;
+- }
+- grefs[i] = err;
++ grefs[i] = gnttab_claim_grant_reference(&gref_head);
++ gnttab_grant_foreign_access_ref(grefs[i], dev->otherend_id,
++ gfn, 0);
+
+ vaddr = vaddr + XEN_PAGE_SIZE;
+ }
+
+ return 0;
+-
+-fail:
+- for (j = 0; j < i; j++)
+- gnttab_end_foreign_access_ref(grefs[j], 0);
+- return err;
+ }
+ EXPORT_SYMBOL_GPL(xenbus_grant_ring);
+