aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorIan Jackson <Ian.Jackson@eu.citrix.com>2012-11-14 11:36:57 +0000
committerIan Jackson <Ian.Jackson@eu.citrix.com>2012-11-14 11:36:57 +0000
commitc870348ef5895bca245cf4fc9c1c3f452ccf9fa1 (patch)
tree89516208242c429d749d2424523f94f25acd8ec6
parentc622d6300c46b498ddc8b2e80413721a96645984 (diff)
downloadxen-c870348ef5895bca245cf4fc9c1c3f452ccf9fa1.tar.gz
xen-c870348ef5895bca245cf4fc9c1c3f452ccf9fa1.tar.bz2
xen-c870348ef5895bca245cf4fc9c1c3f452ccf9fa1.zip
x86/physmap: Prevent incorrect updates of m2p mappings
In certain conditions, such as low memory, set_p2m_entry() can fail. Currently, the p2m and m2p tables will get out of sync because we still update the m2p table after the p2m update has failed. If that happens, subsequent guest-invoked memory operations can cause BUG()s and ASSERT()s to kill Xen. This is fixed by only updating the m2p table iff the p2m was successfully updated. This is a security problem, XSA-22 / CVE-2012-4537. Signed-off-by: Andrew Cooper <andrew.cooper3@citrix.com> Acked-by: Ian Campbell <ian.campbell@citrix.com> Acked-by: Ian Jackson <ian.jackson@eu.citrix.com> Committed-by: Ian Jackson <ian.jackson@eu.citrix.com> xen-unstable changeset: 26149:6b6a4007a609 Backport-requested-by: security@xen.org Committed-by: Ian Jackson <ian.jackson@eu.citrix.com>
-rw-r--r--xen/arch/x86/mm/p2m.c4
1 files changed, 4 insertions, 0 deletions
diff --git a/xen/arch/x86/mm/p2m.c b/xen/arch/x86/mm/p2m.c
index 344fb9928d..674fa05f5b 100644
--- a/xen/arch/x86/mm/p2m.c
+++ b/xen/arch/x86/mm/p2m.c
@@ -654,7 +654,10 @@ guest_physmap_add_entry(struct domain *d, unsigned long gfn,
if ( mfn_valid(_mfn(mfn)) )
{
if ( !set_p2m_entry(p2m, gfn, _mfn(mfn), page_order, t, p2m->default_access) )
+ {
rc = -EINVAL;
+ goto out; /* Failed to update p2m, bail without updating m2p. */
+ }
if ( !p2m_is_grant(t) )
{
for ( i = 0; i < (1UL << page_order); i++ )
@@ -677,6 +680,7 @@ guest_physmap_add_entry(struct domain *d, unsigned long gfn,
}
}
+out:
p2m_unlock(p2m);
return rc;