* Xen Security Advisory 262 - qemu may drive Xen into unbounded loop
@ 2018-05-08 17:00 Xen.org security team
0 siblings, 0 replies; only message in thread
From: Xen.org security team @ 2018-05-08 17:00 UTC (permalink / raw)
To: xen-announce, xen-devel, xen-users, oss-security; +Cc: Xen.org security team
[-- Attachment #1: Type: text/plain, Size: 4007 bytes --]
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA256
Xen Security Advisory XSA-262
version 2
qemu may drive Xen into unbounded loop
UPDATES IN VERSION 2
====================
Public release.
Updated .meta file
ISSUE DESCRIPTION
=================
When Xen sends requests to a device model, the next expected action
inside Xen is tracked using a state field. The requests themselves
are placed in a memory page shared with the device model, so that the
device model can communicate to Xen its progress on the request. The
state field is in the request itself, where the device model may write
to it. Xen correctly rejects invalid state values, but failed to reject
invalid transitions between states. As a result, a device model which
switches a request between two states at the right times can drive Xen
into an unbounded loop.
IMPACT
======
A malicious unprivileged device model can cause a Denial of Service
(DoS) affecting the entire host. Specifically, it may prevent use of a
physical CPU for an indeterminate period of time.
VULNERABLE SYSTEMS
==================
All Xen versions are vulnerable.
Only x86 systems are affected. ARM systems are not affected.
Only HVM guests can expose this vulnerability. PV and PVH guests cannot
expose this vulnerability, but note that the domains being able to
leverage the vulnerability are PV or PVH ones, running the device model.
This vulnerability is only applicable to Xen systems using stub domains.
MITIGATION
==========
Running only PV or PVH guests will avoid this issue.
(The security of a Xen system using stub domains is still better than
with a qemu-dm running as an unrestricted dom0 process. Therefore
users with these configurations should not switch to an unrestricted
dom0 qemu-dm.)
CREDITS
=======
This issue was discovered by Jan Beulich of SUSE.
RESOLUTION
==========
Applying the appropriate attached patch resolves this issue.
xsa262.patch xen-unstable
xsa262-4.10.patch Xen 4.10.x
xsa262-4.9.patch Xen 4.9.x, Xen 4.8.x, Xen 4.7.x
xsa262-4.6.patch Xen 4.6.x
$ sha256sum xsa262*
a5a3458c5efdad282bd769fcab2b94ebfe0a979befae3b4703201fcbf0970cc7 xsa262.meta
5aa73753d3eec8ae391b1364c430df7517bf4bdb3e65a8e6e8431898348f4ad9 xsa262.patch
7196b468b916bf956f8dc0cab20a5c29f8a1bfa4de4e4fa982b7b9c8494e4c0d xsa262-4.6.patch
ec2b6ba9ed1d5e97fed4b54767160a75fe19d67e4519f716739bebdb78816191 xsa262-4.9.patch
91d3b329131b6d434b268c0c55fd4900033fce8b2582bd9278ae967efc980fb0 xsa262-4.10.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-----
Version: GnuPG v1
iQEcBAEBCAAGBQJa8dQhAAoJEIP+FMlX6CvZyCUH/1eCZrElPEOUySjMRbix0EJ8
TW5pWx76PX27Hek4fk+tFxsfDWEqWN4AP9YgjSQKNyXUWEr1oiyq83Vq/JXM6bHt
HSWbrh7sjkkziEGqlOXpryS8/RIE3CZC5nQOTAsPX65tB+2nXkOY5zwuxXM8Ivn6
9p0yitSWd3Ve68PLAhthb/7BDdsAgITtgtxuTDHmDB6h32Fo8m990nD1jbAcP9WR
q32gqXUMdlCf161/viPkSnrRqsnmdzPbXDsAzqtnUeVGNtqb5mI8jqox9Z6JGedG
qMwlZVWO7TzcpO/18KbI8qYypL2/ensEo4bPbvRN7qzA6y8QGwMrLsygtZuBVkw=
=D72A
-----END PGP SIGNATURE-----
[-- Attachment #2: xsa262.meta --]
[-- Type: application/octet-stream, Size: 1819 bytes --]
{
"XSA": 262,
"SupportedVersions": [
"master",
"4.10",
"4.9",
"4.8",
"4.7",
"4.6"
],
"Trees": [
"xen"
],
"Recipes": {
"4.10": {
"Recipes": {
"xen": {
"StableRef": "99e50001bea6f3d777b86bbb9bb41ef66ba47974",
"Prereqs": [
260,
261
],
"Patches": [
"xsa262-4.10.patch"
]
}
}
},
"4.6": {
"Recipes": {
"xen": {
"StableRef": "927aca70011f83c44294f90275c18a0b3f7d7169",
"Prereqs": [
260,
261
],
"Patches": [
"xsa262-4.6.patch"
]
}
}
},
"4.7": {
"Recipes": {
"xen": {
"StableRef": "a8ef07566fa8fe9a2e8db745014d93e259b66785",
"Prereqs": [
260,
261
],
"Patches": [
"xsa262-4.9.patch"
]
}
}
},
"4.8": {
"Recipes": {
"xen": {
"StableRef": "1052a2168ed62999b35319a435c16da884f5f0e2",
"Prereqs": [
260,
261
],
"Patches": [
"xsa262-4.9.patch"
]
}
}
},
"4.9": {
"Recipes": {
"xen": {
"StableRef": "7866e115f9c624b0669997fcc393b489ef3c38a2",
"Prereqs": [
260,
261
],
"Patches": [
"xsa262-4.9.patch"
]
}
}
},
"master": {
"Recipes": {
"xen": {
"StableRef": "d80af845de7a4db01a4a3b4d779e0e0dcb5e738b",
"Prereqs": [
260,
261
],
"Patches": [
"xsa262.patch"
]
}
}
}
}
}
[-- Attachment #3: xsa262.patch --]
[-- Type: application/octet-stream, Size: 2986 bytes --]
From: Jan Beulich <jbeulich@suse.com>
Subject: x86/HVM: guard against emulator driving ioreq state in weird ways
In the case where hvm_wait_for_io() calls wait_on_xen_event_channel(),
p->state ends up being read twice in succession: once to determine that
state != p->state, and then again at the top of the loop. This gives a
compromised emulator a chance to change the state back between the two
reads, potentially keeping Xen in a loop indefinitely.
Instead:
* Read p->state once in each of the wait_on_xen_event_channel() tests,
* re-use that value the next time around,
* and insist that the states continue to transition "forward" (with the
exception of the transition to STATE_IOREQ_NONE).
This is XSA-262.
Signed-off-by: Jan Beulich <jbeulich@suse.com>
Reviewed-by: George Dunlap <george.dunlap@citrix.com>
---
v3: Use George's wording for the description.
v2: Add 2nd smp_rmb().
---
TBD: I'm not sure pulling out the IOREQ_NONE handling ahead of the new
if() is really necessary: The guest is liable to die anyway if one
of its emulators has died.
--- a/xen/arch/x86/hvm/ioreq.c
+++ b/xen/arch/x86/hvm/ioreq.c
@@ -128,14 +128,17 @@ static void hvm_io_assist(struct hvm_ior
static bool hvm_wait_for_io(struct hvm_ioreq_vcpu *sv, ioreq_t *p)
{
+ unsigned int prev_state = STATE_IOREQ_NONE;
+
while ( sv->pending )
{
unsigned int state = p->state;
smp_rmb();
- switch ( state )
+
+ recheck:
+ if ( unlikely(state == STATE_IOREQ_NONE) )
{
- case STATE_IOREQ_NONE:
/*
* The only reason we should see this case is when an
* emulator is dying and it races with an I/O being
@@ -143,14 +146,30 @@ static bool hvm_wait_for_io(struct hvm_i
*/
hvm_io_assist(sv, ~0ul);
break;
+ }
+
+ if ( unlikely(state < prev_state) )
+ {
+ gdprintk(XENLOG_ERR, "Weird HVM ioreq state transition %u -> %u\n",
+ prev_state, state);
+ sv->pending = false;
+ domain_crash(sv->vcpu->domain);
+ return false; /* bail */
+ }
+
+ switch ( prev_state = state )
+ {
case STATE_IORESP_READY: /* IORESP_READY -> NONE */
p->state = STATE_IOREQ_NONE;
hvm_io_assist(sv, p->data);
break;
case STATE_IOREQ_READY: /* IOREQ_{READY,INPROCESS} -> IORESP_READY */
case STATE_IOREQ_INPROCESS:
- wait_on_xen_event_channel(sv->ioreq_evtchn, p->state != state);
- break;
+ wait_on_xen_event_channel(sv->ioreq_evtchn,
+ ({ state = p->state;
+ smp_rmb();
+ state != prev_state; }));
+ goto recheck;
default:
gdprintk(XENLOG_ERR, "Weird HVM iorequest state %u\n", state);
sv->pending = false;
[-- Attachment #4: xsa262-4.6.patch --]
[-- Type: application/octet-stream, Size: 2736 bytes --]
From: Jan Beulich <jbeulich@suse.com>
Subject: x86/HVM: guard against emulator driving ioreq state in weird ways
In the case where hvm_wait_for_io() calls wait_on_xen_event_channel(),
p->state ends up being read twice in succession: once to determine that
state != p->state, and then again at the top of the loop. This gives a
compromised emulator a chance to change the state back between the two
reads, potentially keeping Xen in a loop indefinitely.
Instead:
* Read p->state once in each of the wait_on_xen_event_channel() tests,
* re-use that value the next time around,
* and insist that the states continue to transition "forward" (with the
exception of the transition to STATE_IOREQ_NONE).
This is XSA-262.
Signed-off-by: Jan Beulich <jbeulich@suse.com>
Reviewed-by: George Dunlap <george.dunlap@citrix.com>
--- a/xen/arch/x86/hvm/hvm.c
+++ b/xen/arch/x86/hvm/hvm.c
@@ -453,14 +453,17 @@ static void hvm_io_assist(struct hvm_ior
static bool_t hvm_wait_for_io(struct hvm_ioreq_vcpu *sv, ioreq_t *p)
{
+ unsigned int prev_state = STATE_IOREQ_NONE;
+
while ( sv->pending )
{
unsigned int state = p->state;
- rmb();
- switch ( state )
+ smp_rmb();
+
+ recheck:
+ if ( unlikely(state == STATE_IOREQ_NONE) )
{
- case STATE_IOREQ_NONE:
/*
* The only reason we should see this case is when an
* emulator is dying and it races with an I/O being
@@ -468,14 +471,30 @@ static bool_t hvm_wait_for_io(struct hvm
*/
hvm_io_assist(sv, ~0ul);
break;
+ }
+
+ if ( unlikely(state < prev_state) )
+ {
+ gdprintk(XENLOG_ERR, "Weird HVM ioreq state transition %u -> %u\n",
+ prev_state, state);
+ sv->pending = 0;
+ domain_crash(sv->vcpu->domain);
+ return 0; /* bail */
+ }
+
+ switch ( prev_state = state )
+ {
case STATE_IORESP_READY: /* IORESP_READY -> NONE */
p->state = STATE_IOREQ_NONE;
hvm_io_assist(sv, p->data);
break;
case STATE_IOREQ_READY: /* IOREQ_{READY,INPROCESS} -> IORESP_READY */
case STATE_IOREQ_INPROCESS:
- wait_on_xen_event_channel(sv->ioreq_evtchn, p->state != state);
- break;
+ wait_on_xen_event_channel(sv->ioreq_evtchn,
+ ({ state = p->state;
+ smp_rmb();
+ state != prev_state; }));
+ goto recheck;
default:
gdprintk(XENLOG_ERR, "Weird HVM iorequest state %u\n", state);
sv->pending = 0;
[-- Attachment #5: xsa262-4.9.patch --]
[-- Type: application/octet-stream, Size: 2738 bytes --]
From: Jan Beulich <jbeulich@suse.com>
Subject: x86/HVM: guard against emulator driving ioreq state in weird ways
In the case where hvm_wait_for_io() calls wait_on_xen_event_channel(),
p->state ends up being read twice in succession: once to determine that
state != p->state, and then again at the top of the loop. This gives a
compromised emulator a chance to change the state back between the two
reads, potentially keeping Xen in a loop indefinitely.
Instead:
* Read p->state once in each of the wait_on_xen_event_channel() tests,
* re-use that value the next time around,
* and insist that the states continue to transition "forward" (with the
exception of the transition to STATE_IOREQ_NONE).
This is XSA-262.
Signed-off-by: Jan Beulich <jbeulich@suse.com>
Reviewed-by: George Dunlap <george.dunlap@citrix.com>
--- a/xen/arch/x86/hvm/ioreq.c
+++ b/xen/arch/x86/hvm/ioreq.c
@@ -87,14 +87,17 @@ static void hvm_io_assist(struct hvm_ior
static bool_t hvm_wait_for_io(struct hvm_ioreq_vcpu *sv, ioreq_t *p)
{
+ unsigned int prev_state = STATE_IOREQ_NONE;
+
while ( sv->pending )
{
unsigned int state = p->state;
- rmb();
- switch ( state )
+ smp_rmb();
+
+ recheck:
+ if ( unlikely(state == STATE_IOREQ_NONE) )
{
- case STATE_IOREQ_NONE:
/*
* The only reason we should see this case is when an
* emulator is dying and it races with an I/O being
@@ -102,14 +105,30 @@ static bool_t hvm_wait_for_io(struct hvm
*/
hvm_io_assist(sv, ~0ul);
break;
+ }
+
+ if ( unlikely(state < prev_state) )
+ {
+ gdprintk(XENLOG_ERR, "Weird HVM ioreq state transition %u -> %u\n",
+ prev_state, state);
+ sv->pending = 0;
+ domain_crash(sv->vcpu->domain);
+ return 0; /* bail */
+ }
+
+ switch ( prev_state = state )
+ {
case STATE_IORESP_READY: /* IORESP_READY -> NONE */
p->state = STATE_IOREQ_NONE;
hvm_io_assist(sv, p->data);
break;
case STATE_IOREQ_READY: /* IOREQ_{READY,INPROCESS} -> IORESP_READY */
case STATE_IOREQ_INPROCESS:
- wait_on_xen_event_channel(sv->ioreq_evtchn, p->state != state);
- break;
+ wait_on_xen_event_channel(sv->ioreq_evtchn,
+ ({ state = p->state;
+ smp_rmb();
+ state != prev_state; }));
+ goto recheck;
default:
gdprintk(XENLOG_ERR, "Weird HVM iorequest state %u\n", state);
sv->pending = 0;
[-- Attachment #6: xsa262-4.10.patch --]
[-- Type: application/octet-stream, Size: 2748 bytes --]
From: Jan Beulich <jbeulich@suse.com>
Subject: x86/HVM: guard against emulator driving ioreq state in weird ways
In the case where hvm_wait_for_io() calls wait_on_xen_event_channel(),
p->state ends up being read twice in succession: once to determine that
state != p->state, and then again at the top of the loop. This gives a
compromised emulator a chance to change the state back between the two
reads, potentially keeping Xen in a loop indefinitely.
Instead:
* Read p->state once in each of the wait_on_xen_event_channel() tests,
* re-use that value the next time around,
* and insist that the states continue to transition "forward" (with the
exception of the transition to STATE_IOREQ_NONE).
This is XSA-262.
Signed-off-by: Jan Beulich <jbeulich@suse.com>
Reviewed-by: George Dunlap <george.dunlap@citrix.com>
--- a/xen/arch/x86/hvm/ioreq.c
+++ b/xen/arch/x86/hvm/ioreq.c
@@ -87,14 +87,17 @@ static void hvm_io_assist(struct hvm_ior
static bool hvm_wait_for_io(struct hvm_ioreq_vcpu *sv, ioreq_t *p)
{
+ unsigned int prev_state = STATE_IOREQ_NONE;
+
while ( sv->pending )
{
unsigned int state = p->state;
- rmb();
- switch ( state )
+ smp_rmb();
+
+ recheck:
+ if ( unlikely(state == STATE_IOREQ_NONE) )
{
- case STATE_IOREQ_NONE:
/*
* The only reason we should see this case is when an
* emulator is dying and it races with an I/O being
@@ -102,14 +105,30 @@ static bool hvm_wait_for_io(struct hvm_i
*/
hvm_io_assist(sv, ~0ul);
break;
+ }
+
+ if ( unlikely(state < prev_state) )
+ {
+ gdprintk(XENLOG_ERR, "Weird HVM ioreq state transition %u -> %u\n",
+ prev_state, state);
+ sv->pending = false;
+ domain_crash(sv->vcpu->domain);
+ return false; /* bail */
+ }
+
+ switch ( prev_state = state )
+ {
case STATE_IORESP_READY: /* IORESP_READY -> NONE */
p->state = STATE_IOREQ_NONE;
hvm_io_assist(sv, p->data);
break;
case STATE_IOREQ_READY: /* IOREQ_{READY,INPROCESS} -> IORESP_READY */
case STATE_IOREQ_INPROCESS:
- wait_on_xen_event_channel(sv->ioreq_evtchn, p->state != state);
- break;
+ wait_on_xen_event_channel(sv->ioreq_evtchn,
+ ({ state = p->state;
+ smp_rmb();
+ state != prev_state; }));
+ goto recheck;
default:
gdprintk(XENLOG_ERR, "Weird HVM iorequest state %u\n", state);
sv->pending = false;
[-- Attachment #7: Type: text/plain, Size: 157 bytes --]
_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xenproject.org
https://lists.xenproject.org/mailman/listinfo/xen-devel
^ permalink raw reply [flat|nested] only message in thread
only message in thread, other threads:[~2018-05-08 17:00 UTC | newest]
Thread overview: (only message) (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2018-05-08 17:00 Xen Security Advisory 262 - qemu may drive Xen into unbounded loop Xen.org security team
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).