-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA256
Xen Security Advisory CVE-2026-102703,CVE-2026-102704 / XSA-523
version 2
arbitrary read/write via grant copy
UPDATES IN VERSION 2
====================
Public release.
ISSUE DESCRIPTION
=================
A common access pattern is a batch of Grant Copy operations acting on
adjacent address ranges in the same source or destination page. For
performance reasons, Xen caches details internally to reuse already
validated data. The conditions on when to re-validate the internal data
were not correct in some cases:
- Frame numbers and grant references could wrongly be mixed up. This
is CVE-2026-102703.
- Copying by frame number (rather than grant reference) is permitted
only when operating on the caller's own memory. The check to enforce
this restriction was misplaced. This is CVE-2026-102704.
IMPACT
======
A malicious guest can read and write arbitrary memory, belonging to
other domains, including Dom0.
VULNERABLE SYSTEMS
==================
All Xen versions from 4.6 onwards are vulnerable. Xen versions 4.5 and
earlier are not vulnerable.
MITIGATION
==========
There is no known mitigation.
CREDITS
=======
This issue was discovered by Anthropic using Claude, then validated by
Stephan Lipp of Ada Logics.
It was then independently reported by the CodeAnt AI Security Research
Team.
RESOLUTION
==========
Applying the appropriate set of attached patches resolves this issue.
Note that patches for released versions are generally prepared to
apply to the stable branches, and may not apply cleanly to the most
recent release tarball. Downstreams are encouraged to update to the
tip of the stable branch before applying these patches.
xsa523-?.patch xen-unstable - Xen 4.19.x
xsa523-4.18-?.patch Xen 4.18.x - Xen 4.17.x
$ sha256sum xsa523*
87562e68c584dcc6b568348e7ba6cfde592798cb89f372364792afda65aa6895 xsa523-1.patch
9cd4e76fa3587f491f5bb0f895f375fcf24df8bd9bdf602c343081e7411b92f0 xsa523-2.patch
c1accb1fa55176cb6191e091d93198068630acbc6529966738669a43d5c2e38e xsa523-4.18-1.patch
efc16fe8830066276fb50f01f24a358194a752507077fdb61a60f891dc1a7019 xsa523-4.18-2.patch
$
DEPLOYMENT DURING EMBARGO
=========================
Deployment of the patches and/or mitigations described above (or
others which are substantially similar) is permitted during the
embargo, even on public-facing systems with untrusted guest users and
administrators.
But: Distribution of updated software is prohibited (except to other
members of the predisclosure list).
Predisclosure list members who wish to deploy significantly different
patches and/or mitigations, please contact the Xen Project Security
Team.
(Note: this during-embargo deployment notice is retained in
post-embargo publicly released Xen Project advisories, even though it
is then no longer applicable. This is to enable the community to have
oversight of the Xen Project Security Team's decisionmaking.)
For more information about permissible uses of embargoed information,
consult the Xen Project community's agreed Security Policy:
http://www.xenproject.org/security-policy.html
-----BEGIN PGP SIGNATURE-----
iQFABAEBCAAqFiEEI+MiLBRfRHX6gGCng/4UyVfoK9kFAmrpzHcMHHBncEB4ZW4u
b3JnAAoJEIP+FMlX6CvZYTAIALOhpiCcbIvbmpr8/yLSFfLXJ30HIq+rihtrrwHi
IYuUujGKDMMfZ+peGDzjUvWdSpeccHVqzxYyQbeqKN+bxeiRHyPaquaKGgMJgPgg
aI8/Ee5zeCBESEsAAI6Z6REXPT/ViL1MY4+gI8cGjD3CIfoBoBhHqDBxtDlkNtH6
bFH4E6CsLGPe1PELDBjEaqwFPiY03DItRBywXi9ygfATn47EnViQOlGSZm4cMIaX
wdT5dJKydXjvscrglijQSKUzhqC8qaTPwxF7pNPZWjw06QNBQUvLQi68iWgA1Hp/
ACiQV+gJuY+qEH93+UbQkxl7k0DBXfZLo6CxdrKupI3MVB4=
=SYnT
-----END PGP SIGNATURE-----
From: Jan Beulich <jbeulich@suse.com>
Subject: gnttab: complete checking in gnttab_copy_buf_valid()
The ->have_grant field needs checking not only ahead of comparing GREFs,
but also ahead of comparing MFNs. Else a (likely invalid) GREF from an
earlier batch element can be mistaken for a (possibly valid) MFN.
This is CVE-2026-102703, part of XSA-523.
Fixes: d28f42f2703e ("grant-table: defer releasing pages acquired in a grant copy")
Assisted-by: Claude
Reported-by: Stephan Lipp <Stephan@Adalogics.com>
Reported-by: CodeAnt AI Security Research <securityresearch@codeant.ai>
Signed-off-by: Jan Beulich <jbeulich@suse.com>
Reviewed-by: Andrew Cooper <andrew.cooper3@citrix.com>
diff --git a/xen/common/grant_table.c b/xen/common/grant_table.c
index b15805f3f94d..3dc5ff88da85 100644
--- a/xen/common/grant_table.c
+++ b/xen/common/grant_table.c
@@ -3083,10 +3083,10 @@ static bool gnttab_copy_buf_valid(
const struct gnttab_copy_ptr *p, const struct gnttab_copy_buf *b,
bool has_gref)
{
- if ( !b->virt )
+ if ( !b->virt || b->have_grant != has_gref )
return 0;
if ( has_gref )
- return b->have_grant && p->u.ref == b->ptr.u.ref;
+ return p->u.ref == b->ptr.u.ref;
return p->u.gmfn == b->ptr.u.gmfn;
}
From: Jan Beulich <jbeulich@suse.com>
Subject: gnttab: move "only local domain may copy by frame" check
gnttab_copy_one() calls gnttab_copy_lock_domain{s,}() only conditionally.
The non-GREF check towards the requestor being DOMID_SELF, however, needs
doing on every batch element. Move the check into gnttab_copy_claim_buf()
to achieve that.
This is CVE-2026-102704, part of XSA-523.
Fixes: d28f42f2703e ("grant-table: defer releasing pages acquired in a grant copy")
Assisted-by: Claude
Reported-by: Stephan Lipp <Stephan@Adalogics.com>
Reported-by: CodeAnt AI Security Research <securityresearch@codeant.ai>
Signed-off-by: Jan Beulich <jbeulich@suse.com>
Reviewed-by: Andrew Cooper <andrew.cooper3@citrix.com>
diff --git a/xen/common/grant_table.c b/xen/common/grant_table.c
index 3dc5ff88da85..5e79c012b695 100644
--- a/xen/common/grant_table.c
+++ b/xen/common/grant_table.c
@@ -2936,13 +2936,8 @@ struct gnttab_copy_buf {
bool have_type;
};
-static int gnttab_copy_lock_domain(domid_t domid, bool is_gref,
- struct gnttab_copy_buf *buf)
+static int gnttab_copy_lock_domain(domid_t domid, struct gnttab_copy_buf *buf)
{
- /* Only DOMID_SELF may reference via frame. */
- if ( domid != DOMID_SELF && !is_gref )
- return GNTST_permission_denied;
-
buf->domain = rcu_lock_domain_by_any_id(domid);
if ( !buf->domain )
@@ -2974,12 +2969,10 @@ static int gnttab_copy_lock_domains(const struct gnttab_copy *op,
{
int rc;
- rc = gnttab_copy_lock_domain(op->source.domid,
- op->flags & GNTCOPY_source_gref, src);
+ rc = gnttab_copy_lock_domain(op->source.domid, src);
if ( rc < 0 )
goto error;
- rc = gnttab_copy_lock_domain(op->dest.domid,
- op->flags & GNTCOPY_dest_gref, dest);
+ rc = gnttab_copy_lock_domain(op->dest.domid, dest);
if ( rc < 0 )
goto error;
@@ -3042,6 +3035,9 @@ static int gnttab_copy_claim_buf(const struct gnttab_copy *op,
buf->ptr.u.ref = ptr->u.ref;
buf->have_grant = 1;
}
+ /* Only DOMID_SELF may reference via frame. */
+ else if ( ptr->domid != DOMID_SELF )
+ return GNTST_permission_denied;
else
{
rc = get_paged_frame(ptr->u.gmfn, &buf->mfn, &buf->page,
From: Jan Beulich <jbeulich@suse.com>
Subject: gnttab: complete checking in gnttab_copy_buf_valid()
The ->have_grant field needs checking not only ahead of comparing GREFs,
but also ahead of comparing MFNs. Else a (likely invalid) GREF from an
earlier batch element can be mistaken for a (possibly valid) MFN.
This is CVE-2026-102703, part of XSA-523.
Fixes: d28f42f2703e ("grant-table: defer releasing pages acquired in a grant copy")
Assisted-by: Claude
Reported-by: Stephan Lipp <Stephan@Adalogics.com>
Reported-by: CodeAnt AI Security Research <securityresearch@codeant.ai>
Signed-off-by: Jan Beulich <jbeulich@suse.com>
Reviewed-by: Andrew Cooper <andrew.cooper3@citrix.com>
diff --git a/xen/common/grant_table.c b/xen/common/grant_table.c
index 742c9797c535..842d43684849 100644
--- a/xen/common/grant_table.c
+++ b/xen/common/grant_table.c
@@ -3081,10 +3081,10 @@ static bool_t gnttab_copy_buf_valid(const struct gnttab_copy_ptr *p,
const struct gnttab_copy_buf *b,
bool_t has_gref)
{
- if ( !b->virt )
+ if ( !b->virt || b->have_grant != has_gref )
return 0;
if ( has_gref )
- return b->have_grant && p->u.ref == b->ptr.u.ref;
+ return p->u.ref == b->ptr.u.ref;
return p->u.gmfn == b->ptr.u.gmfn;
}
From: Jan Beulich <jbeulich@suse.com>
Subject: gnttab: move "only local domain may copy by frame" check
gnttab_copy_one() calls gnttab_copy_lock_domain{s,}() only conditionally.
The non-GREF check towards the requestor being DOMID_SELF, however, needs
doing on every batch element. Move the check into gnttab_copy_claim_buf()
to achieve that.
This is CVE-2026-102704, part of XSA-523.
Fixes: d28f42f2703e ("grant-table: defer releasing pages acquired in a grant copy")
Assisted-by: Claude
Reported-by: Stephan Lipp <Stephan@Adalogics.com>
Reported-by: CodeAnt AI Security Research <securityresearch@codeant.ai>
Signed-off-by: Jan Beulich <jbeulich@suse.com>
Reviewed-by: Andrew Cooper <andrew.cooper3@citrix.com>
diff --git a/xen/common/grant_table.c b/xen/common/grant_table.c
index 842d43684849..03543fc335a9 100644
--- a/xen/common/grant_table.c
+++ b/xen/common/grant_table.c
@@ -2934,13 +2934,8 @@ struct gnttab_copy_buf {
bool_t have_type;
};
-static int gnttab_copy_lock_domain(domid_t domid, bool is_gref,
- struct gnttab_copy_buf *buf)
+static int gnttab_copy_lock_domain(domid_t domid, struct gnttab_copy_buf *buf)
{
- /* Only DOMID_SELF may reference via frame. */
- if ( domid != DOMID_SELF && !is_gref )
- return GNTST_permission_denied;
-
buf->domain = rcu_lock_domain_by_any_id(domid);
if ( !buf->domain )
@@ -2972,12 +2967,10 @@ static int gnttab_copy_lock_domains(const struct gnttab_copy *op,
{
int rc;
- rc = gnttab_copy_lock_domain(op->source.domid,
- op->flags & GNTCOPY_source_gref, src);
+ rc = gnttab_copy_lock_domain(op->source.domid, src);
if ( rc < 0 )
goto error;
- rc = gnttab_copy_lock_domain(op->dest.domid,
- op->flags & GNTCOPY_dest_gref, dest);
+ rc = gnttab_copy_lock_domain(op->dest.domid, dest);
if ( rc < 0 )
goto error;
@@ -3040,6 +3033,9 @@ static int gnttab_copy_claim_buf(const struct gnttab_copy *op,
buf->ptr.u.ref = ptr->u.ref;
buf->have_grant = 1;
}
+ /* Only DOMID_SELF may reference via frame. */
+ else if ( ptr->domid != DOMID_SELF )
+ return GNTST_permission_denied;
else
{
rc = get_paged_frame(ptr->u.gmfn, &buf->mfn, &buf->page,
© 2016 - 2026 Red Hat, Inc.