* Xen Security Advisory 221 (CVE-2017-10917) - NULL pointer deref in event channel poll
@ 2017-07-07 13:54 Xen.org security team
0 siblings, 0 replies; only message in thread
From: Xen.org security team @ 2017-07-07 13:54 UTC (permalink / raw)
To: xen-announce, xen-devel, xen-users, oss-security; +Cc: Xen.org security team
[-- Attachment #1: Type: text/plain, Size: 3010 bytes --]
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA256
Xen Security Advisory CVE-2017-10917 / XSA-221
version 3
NULL pointer deref in event channel poll
UPDATES IN VERSION 3
====================
CVE assigned.
ISSUE DESCRIPTION
=================
When polling event channels, in general arbitrary port numbers can be
specified. Specifically, there is no requirement that a polled event
channel ports has ever been created. When the code was generalised
from an earlier implementation, introducing some intermediate
pointers, a check should have been made that these intermediate
pointers are non-NULL. However, that check was omitted.
IMPACT
======
A malicious or buggy guest may cause the hypervisor to access
addresses it doesn't control, usually leading to a host crash (Denial
of Service). Information leaks cannot be excluded.
VULNERABLE SYSTEMS
==================
Xen versions 4.4 and newer are vulnerable. Xen versions 4.3 and
earlier are not affected.
Both x86 and ARM systems are vulnerable.
While all guest kinds can cause a Denial of Service, only x86 PV guests
may be able to leverage the possible information leaks.
MITIGATION
==========
There is no known mitigation.
CREDITS
=======
This issue was discovered by Ankur Arora of Oracle.
RESOLUTION
==========
Applying the appropriate attached patch resolves this issue.
xsa221.patch Xen 4.4.x and later, including xen-unstable
$ sha256sum xsa221*
2425396a713466808b0f75f91337be4dd20a4dee7733972b04489773c6e97655 xsa221.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
iQEcBAEBCAAGBQJZX5IrAAoJEIP+FMlX6CvZvrQH/iiAi2rNN1mXhC9wRArVRhN4
CHQLswKxeCfL38sAkOCD1oshNsf5Cskv5WI0/row0SzUPuwsdglPBvpXjUdC+4c/
TNm119wRA3XigJl/eW+OlenA/QdXIjp7D3/IqVu5fEZ+bGntOgo7q4GhgsRRl2SR
mKMgoN7/PCaLd5KtoCr76FygqBcTHYQDswa97alNXdwALC5PPb1R8lO+GDq4FPNj
VYCsynBjVhScnbayEWmbPLXvkaz+6u2VccpfWDIS7i+dyTnAVTNkqS+Mzjsk07za
FRisjlyc3rZTF/7nJ9Vtk4bCPC3+zmKsCTfzbOqdDYu9VJryK7gZl8yksfqw37s=
=HElV
-----END PGP SIGNATURE-----
[-- Attachment #2: xsa221.patch --]
[-- Type: application/octet-stream, Size: 7411 bytes --]
From: Jan Beulich <jbeulich@suse.com>
Subject: evtchn: avoid NULL derefs
Commit fbbd5009e6 ("evtchn: refactor low-level event channel port ops")
added a de-reference of the struct evtchn pointer for a port without
first making sure the bucket pointer is non-NULL. This de-reference is
actually entirely unnecessary, as all relevant callers (beyond the
problematic do_poll()) already hold the port number in their hands, and
the actual leaf functions need nothing else.
For FIFO event channels there's a second problem in that the ordering
of reads and updates to ->num_evtchns and ->event_array[] was so far
undefined (the read side isn't always holding the domain's event lock).
Add respective barriers.
This is XSA-221.
Reported-by: Ankur Arora <ankur.a.arora@oracle.com>
Signed-off-by: Jan Beulich <jbeulich@suse.com>
--- a/xen/arch/x86/irq.c
+++ b/xen/arch/x86/irq.c
@@ -1486,7 +1486,7 @@ int pirq_guest_unmask(struct domain *d)
{
pirq = pirqs[i]->pirq;
if ( pirqs[i]->masked &&
- !evtchn_port_is_masked(d, evtchn_from_port(d, pirqs[i]->evtchn)) )
+ !evtchn_port_is_masked(d, pirqs[i]->evtchn) )
pirq_guest_eoi(pirqs[i]);
}
} while ( ++pirq < d->nr_pirqs && n == ARRAY_SIZE(pirqs) );
@@ -2244,7 +2244,6 @@ static void dump_irqs(unsigned char key)
int i, irq, pirq;
struct irq_desc *desc;
irq_guest_action_t *action;
- struct evtchn *evtchn;
struct domain *d;
const struct pirq *info;
unsigned long flags;
@@ -2287,11 +2286,10 @@ static void dump_irqs(unsigned char key)
d = action->guest[i];
pirq = domain_irq_to_pirq(d, irq);
info = pirq_info(d, pirq);
- evtchn = evtchn_from_port(d, info->evtchn);
printk("%u:%3d(%c%c%c)",
d->domain_id, pirq,
- (evtchn_port_is_pending(d, evtchn) ? 'P' : '-'),
- (evtchn_port_is_masked(d, evtchn) ? 'M' : '-'),
+ evtchn_port_is_pending(d, info->evtchn) ? 'P' : '-',
+ evtchn_port_is_masked(d, info->evtchn) ? 'M' : '-',
(info->masked ? 'M' : '-'));
if ( i != action->nr_guests )
printk(",");
--- a/xen/common/event_2l.c
+++ b/xen/common/event_2l.c
@@ -61,16 +61,20 @@ static void evtchn_2l_unmask(struct doma
}
}
-static bool_t evtchn_2l_is_pending(struct domain *d,
- const struct evtchn *evtchn)
+static bool_t evtchn_2l_is_pending(struct domain *d, evtchn_port_t port)
{
- return test_bit(evtchn->port, &shared_info(d, evtchn_pending));
+ unsigned int max_ports = BITS_PER_EVTCHN_WORD(d) * BITS_PER_EVTCHN_WORD(d);
+
+ ASSERT(port < max_ports);
+ return port < max_ports && test_bit(port, &shared_info(d, evtchn_pending));
}
-static bool_t evtchn_2l_is_masked(struct domain *d,
- const struct evtchn *evtchn)
+static bool_t evtchn_2l_is_masked(struct domain *d, evtchn_port_t port)
{
- return test_bit(evtchn->port, &shared_info(d, evtchn_mask));
+ unsigned int max_ports = BITS_PER_EVTCHN_WORD(d) * BITS_PER_EVTCHN_WORD(d);
+
+ ASSERT(port < max_ports);
+ return port >= max_ports || test_bit(port, &shared_info(d, evtchn_mask));
}
static void evtchn_2l_print_state(struct domain *d,
--- a/xen/common/event_channel.c
+++ b/xen/common/event_channel.c
@@ -1380,8 +1380,8 @@ static void domain_dump_evtchn_info(stru
printk(" %4u [%d/%d/",
port,
- !!evtchn_port_is_pending(d, chn),
- !!evtchn_port_is_masked(d, chn));
+ evtchn_port_is_pending(d, port),
+ evtchn_port_is_masked(d, port));
evtchn_port_print_state(d, chn);
printk("]: s=%d n=%d x=%d",
chn->state, chn->notify_vcpu_id, chn->xen_consumer);
--- a/xen/common/event_fifo.c
+++ b/xen/common/event_fifo.c
@@ -27,6 +27,12 @@ static inline event_word_t *evtchn_fifo_
if ( unlikely(port >= d->evtchn_fifo->num_evtchns) )
return NULL;
+ /*
+ * Callers aren't required to hold d->event_lock, so we need to synchronize
+ * with add_page_to_event_array().
+ */
+ smp_rmb();
+
p = port / EVTCHN_FIFO_EVENT_WORDS_PER_PAGE;
w = port % EVTCHN_FIFO_EVENT_WORDS_PER_PAGE;
@@ -287,24 +293,22 @@ static void evtchn_fifo_unmask(struct do
evtchn_fifo_set_pending(v, evtchn);
}
-static bool_t evtchn_fifo_is_pending(struct domain *d,
- const struct evtchn *evtchn)
+static bool_t evtchn_fifo_is_pending(struct domain *d, evtchn_port_t port)
{
event_word_t *word;
- word = evtchn_fifo_word_from_port(d, evtchn->port);
+ word = evtchn_fifo_word_from_port(d, port);
if ( unlikely(!word) )
return 0;
return test_bit(EVTCHN_FIFO_PENDING, word);
}
-static bool_t evtchn_fifo_is_masked(struct domain *d,
- const struct evtchn *evtchn)
+static bool_t evtchn_fifo_is_masked(struct domain *d, evtchn_port_t port)
{
event_word_t *word;
- word = evtchn_fifo_word_from_port(d, evtchn->port);
+ word = evtchn_fifo_word_from_port(d, port);
if ( unlikely(!word) )
return 1;
@@ -593,6 +597,10 @@ static int add_page_to_event_array(struc
return rc;
d->evtchn_fifo->event_array[slot] = virt;
+
+ /* Synchronize with evtchn_fifo_word_from_port(). */
+ smp_wmb();
+
d->evtchn_fifo->num_evtchns += EVTCHN_FIFO_EVENT_WORDS_PER_PAGE;
/*
--- a/xen/common/schedule.c
+++ b/xen/common/schedule.c
@@ -965,7 +965,7 @@ static long do_poll(struct sched_poll *s
goto out;
rc = 0;
- if ( evtchn_port_is_pending(d, evtchn_from_port(d, port)) )
+ if ( evtchn_port_is_pending(d, port) )
goto out;
}
--- a/xen/include/xen/event.h
+++ b/xen/include/xen/event.h
@@ -137,8 +137,8 @@ struct evtchn_port_ops {
void (*set_pending)(struct vcpu *v, struct evtchn *evtchn);
void (*clear_pending)(struct domain *d, struct evtchn *evtchn);
void (*unmask)(struct domain *d, struct evtchn *evtchn);
- bool_t (*is_pending)(struct domain *d, const struct evtchn *evtchn);
- bool_t (*is_masked)(struct domain *d, const struct evtchn *evtchn);
+ bool_t (*is_pending)(struct domain *d, evtchn_port_t port);
+ bool_t (*is_masked)(struct domain *d, evtchn_port_t port);
/*
* Is the port unavailable because it's still being cleaned up
* after being closed?
@@ -175,15 +175,15 @@ static inline void evtchn_port_unmask(st
}
static inline bool_t evtchn_port_is_pending(struct domain *d,
- const struct evtchn *evtchn)
+ evtchn_port_t port)
{
- return d->evtchn_port_ops->is_pending(d, evtchn);
+ return d->evtchn_port_ops->is_pending(d, port);
}
static inline bool_t evtchn_port_is_masked(struct domain *d,
- const struct evtchn *evtchn)
+ evtchn_port_t port)
{
- return d->evtchn_port_ops->is_masked(d, evtchn);
+ return d->evtchn_port_ops->is_masked(d, port);
}
static inline bool_t evtchn_port_is_busy(struct domain *d, evtchn_port_t port)
[-- Attachment #3: Type: text/plain, Size: 127 bytes --]
_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel
^ permalink raw reply [flat|nested] only message in thread
only message in thread, other threads:[~2017-07-07 13:54 UTC | newest]
Thread overview: (only message) (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2017-07-07 13:54 Xen Security Advisory 221 (CVE-2017-10917) - NULL pointer deref in event channel poll 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).