Xen Security Advisory 392 v4 (CVE-2021-28714,CVE-2021-28715) - Guest can force Linux netback driver to hog large amounts of kernel memory
Xen.org security team <[email protected]> Mon, 20 Dec 2021 12:03:09 +0000
| Newsgroups | gmane.comp.emulators.xen.announce |
|---|---|
| Message-ID | <E1mzHNl-0002XV-04__45901.9460062095$1640001939$gmane$org@xenbits.xenproject.org> |
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA256
Xen Security Advisory CVE-2021-28714,CVE-2021-28715 / XSA-392
version 4
Guest can force Linux netback driver to hog large amounts of kernel memory
UPDATES IN VERSION 4
====================
Public release
ISSUE DESCRIPTION
=================
Incoming data packets for a guest in the Linux kernel's netback driver
are buffered until the guest is ready to process them. There are some
measures taken for avoiding to pile up too much data, but those can
be bypassed by the guest:
There is a timeout how long the client side of an interface can stop
consuming new packets before it is assumed to have stalled, but this
timeout is rather long (60 seconds by default). Using a UDP connection
on a fast interface can easily accumulate gigabytes of data in that
time. (CVE-2021-28715)
The timeout could even never trigger if the guest manages to have only
one free slot in its RX queue ring page and the next package would
require more than one free slot, which may be the case when using GSO,
XDP, or software hashing. (CVE-2021-28714)
IMPACT
======
The Linux kernel's xen-netback backend driver can be forced by guests
to queue arbitrary amounts of network data, finally causing an out of
memory situation in the domain the backend is running in (usually dom0).
VULNERABLE SYSTEMS
==================
All systems using the Linux kernel based network backend xen-netback
are vulnerable.
MITIGATION
==========
Using another PV network backend (e.g. the qemu based "qnic" backend)
will mitigate the problem.
Using a dedicated network driver domain per guest will mitigate the
problem.
RESOLUTION
==========
Applying the attached patches resolves this issue.
xsa392-linux-1.patch Linux 5.15
xsa392-linux-2.patch Linux 5.15
$ sha256sum xsa392*
9cf75e9919415267266a7f69ca0f3dbbafc1c55d4243cff1cb26072e28bb6e26 xsa392-linux-1.patch
f390da9723ed03948855bfc3b112fc11bcc794fc59502d4fc5e8e358321e8684 xsa392-linux-2.patch
$
CREDITS
=======
This issue was discovered by Jürgen Groß of SUSE.
DEPLOYMENT DURING EMBARGO
=========================
Deployment of the *patches* 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).
Deployment of the *mitigations* (switching to driver domains or using
a qemu based backend) is NOT permitted (except where all the affected
systems and VMs are administered and used only by organisations which
are members of the Xen Project Security Issues Predisclosure List).
Specifically, deployment of the mitigations on public cloud systems is
NOT permitted.
This is because the mitigations will result in discoverable changes of
Xenstore entries for the guest.
Deployment of the mitigations is permitted only AFTER the embargo ends.
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/4UyVfoK9kFAmG8sr8MHHBncEB4ZW4u
b3JnAAoJEIP+FMlX6CvZQGsH/igyavZ/s8jbiANP/jVW9/4wegsqqaeaQBEyhP0o
P2wEwX30taFmT+kC/7Rf+62O2vdOJKow4C+JouCKcigDH2+nvkki/gd65cpKLkk4
BKBuSnkTkagdokTPqpQ57zKTe9R5OP4Iw8B01YCI0k08aKE782xbxLr+pac3dw2C
3tB24fdFibrzlXeMbYXM2Aw8aeSWkVjJ40XrW+Xo6k8GdgTZY9SDgTqGAv71g+bJ
liCQheGkQIQPDjFUf6S/ykRCwaQVtnHqThASPoWOwzYto3uvjyMJm74Rr9n6TLzz
WvJLQPDgObyU9RUlUXU3fgCaYgvh2ufuNreQt1d1NY01s04=
=54ve
-----END PGP SIGNATURE-----
xsa392-linux-1.patch
(application/octet-stream, 5.2 KB)
From 8b01ec26b69dfb8fc033600456c7522777c8e183 Mon Sep 17 00:00:00 2001 From: Juergen Gross <[email protected]> Date: Fri, 26 Nov 2021 10:36:57 +0100 Subject: [PATCH 1/2] xen/netback: fix rx queue stall detection Commit 1d5d48523900a4b ("xen-netback: require fewer guest Rx slots when not using GSO") introduced a security problem in netback, as an interface would only be regarded to be stalled if no slot is available in the rx queue ring page. In case the SKB at the head of the queued requests will need more than one rx slot and only one slot is free the stall detection logic will never trigger, as the test for that is only looking for at least one slot to be free. Fix that by testing for the needed number of slots instead of only one slot being available. In order to not have to take the rx queue lock that often, store the number of needed slots in the queue data. As all SKB dequeue operations happen in the rx queue kernel thread this is safe, as long as the number of needed slots is accessed via READ/WRITE_ONCE() only and updates are always done with the rx queue lock held. Add a small helper for obtaining the number of free slots. This is CVE-2021-28714, part of XSA-392 Fixes: 1d5d48523900a4b ("xen-netback: require fewer guest Rx slots when not using GSO") Signed-off-by: Juergen Gross <[email protected]> Reviewed-by: Jan Beulich <[email protected]> --- drivers/net/xen-netback/common.h | 1 + drivers/net/xen-netback/rx.c | 65 ++++++++++++++++++++------------ 2 files changed, 42 insertions(+), 24 deletions(-) diff --git a/drivers/net/xen-netback/common.h b/drivers/net/xen-netback/common.h index 4a16d6e33c09..d9dea4829c86 100644 --- a/drivers/net/xen-netback/common.h +++ b/drivers/net/xen-netback/common.h @@ -203,6 +203,7 @@ struct xenvif_queue { /* Per-queue data for xenvif */ unsigned int rx_queue_max; unsigned int rx_queue_len; unsigned long last_rx_time; + unsigned int rx_slots_needed; bool stalled; struct xenvif_copy_state rx_copy; diff --git a/drivers/net/xen-netback/rx.c b/drivers/net/xen-netback/rx.c index accc991d153f..a8511e27d6c1 100644 --- a/drivers/net/xen-netback/rx.c +++ b/drivers/net/xen-netback/rx.c @@ -33,28 +33,36 @@ #include <xen/xen.h> #include <xen/events.h> -static bool xenvif_rx_ring_slots_available(struct xenvif_queue *queue) +/* + * Update the needed ring page slots for the first SKB queued. + * Note that any call sequence outside the RX thread calling this function + * needs to wake up the RX thread via a call of xenvif_kick_thread() + * afterwards in order to avoid a race with putting the thread to sleep. + */ +static void xenvif_update_needed_slots(struct xenvif_queue *queue, + const struct sk_buff *skb) { - RING_IDX prod, cons; - struct sk_buff *skb; - int needed; - unsigned long flags; - - spin_lock_irqsave(&queue->rx_queue.lock, flags); + unsigned int needed = 0; - skb = skb_peek(&queue->rx_queue); - if (!skb) { - spin_unlock_irqrestore(&queue->rx_queue.lock, flags); - return false; + if (skb) { + needed = DIV_ROUND_UP(skb->len, XEN_PAGE_SIZE); + if (skb_is_gso(skb)) + needed++; + if (skb->sw_hash) + needed++; } - needed = DIV_ROUND_UP(skb->len, XEN_PAGE_SIZE); - if (skb_is_gso(skb)) - needed++; - if (skb->sw_hash) - needed++; + WRITE_ONCE(queue->rx_slots_needed, needed); +} - spin_unlock_irqrestore(&queue->rx_queue.lock, flags); +static bool xenvif_rx_ring_slots_available(struct xenvif_queue *queue) +{ + RING_IDX prod, cons; + unsigned int needed; + + needed = READ_ONCE(queue->rx_slots_needed); + if (!needed) + return false; do { prod = queue->rx.sring->req_prod; @@ -80,6 +88,9 @@ void xenvif_rx_queue_tail(struct xenvif_queue *queue, struct sk_buff *skb) spin_lock_irqsave(&queue->rx_queue.lock, flags); + if (skb_queue_empty(&queue->rx_queue)) + xenvif_update_needed_slots(queue, skb); + __skb_queue_tail(&queue->rx_queue, skb); queue->rx_queue_len += skb->len; @@ -100,6 +111,8 @@ static struct sk_buff *xenvif_rx_dequeue(struct xenvif_queue *queue) skb = __skb_dequeue(&queue->rx_queue); if (skb) { + xenvif_update_needed_slots(queue, skb_peek(&queue->rx_queue)); + queue->rx_queue_len -= skb->len; if (queue->rx_queue_len < queue->rx_queue_max) { struct netdev_queue *txq; @@ -487,27 +500,31 @@ void xenvif_rx_action(struct xenvif_queue *queue) xenvif_rx_copy_flush(queue); } -static bool xenvif_rx_queue_stalled(struct xenvif_queue *queue) +static RING_IDX xenvif_rx_queue_slots(const struct xenvif_queue *queue) { RING_IDX prod, cons; prod = queue->rx.sring->req_prod; cons = queue->rx.req_cons; + return prod - cons; +} + +static bool xenvif_rx_queue_stalled(const struct xenvif_queue *queue) +{ + unsigned int needed = READ_ONCE(queue->rx_slots_needed); + return !queue->stalled && - prod - cons < 1 && + xenvif_rx_queue_slots(queue) < needed && time_after(jiffies, queue->last_rx_time + queue->vif->stall_timeout); } static bool xenvif_rx_queue_ready(struct xenvif_queue *queue) { - RING_IDX prod, cons; - - prod = queue->rx.sring->req_prod; - cons = queue->rx.req_cons; + unsigned int needed = READ_ONCE(queue->rx_slots_needed); - return queue->stalled && prod - cons >= 1; + return queue->stalled && xenvif_rx_queue_slots(queue) >= needed; } bool xenvif_have_rx_work(struct xenvif_queue *queue, bool test_kthread) -- 2.26.2
xsa392-linux-2.patch
(application/octet-stream, 2.6 KB)
From 71492f1f12db956a9eb49e727d12b225dad74205 Mon Sep 17 00:00:00 2001 From: Juergen Gross <[email protected]> Date: Fri, 26 Nov 2021 10:36:57 +0100 Subject: [PATCH 2/2] xen/netback: don't queue unlimited number of packages In case a guest isn't consuming incoming network traffic as fast as it is coming in, xen-netback is buffering network packages in unlimited numbers today. This can result in host OOM situations. Commit f48da8b14d04ca8 ("xen-netback: fix unlimited guest Rx internal queue and carrier flapping") meant to introduce a mechanism to limit the amount of buffered data by stopping the Tx queue when reaching the data limit, but this doesn't work for cases like UDP. When hitting the limit don't queue further SKBs, but drop them instead. In order to be able to tell Rx packages have been dropped increment the rx_dropped statistics counter in this case. It should be noted that the old solution to continue queueing SKBs had the additional problem of an overflow of the 32-bit rx_queue_len value would result in intermittent Tx queue enabling. This is CVE-2021-28715, part of XSA-392 Fixes: f48da8b14d04ca8 ("xen-netback: fix unlimited guest Rx internal queue and carrier flapping") Signed-off-by: Juergen Gross <[email protected]> Reviewed-by: Jan Beulich <[email protected]> --- drivers/net/xen-netback/rx.c | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/drivers/net/xen-netback/rx.c b/drivers/net/xen-netback/rx.c index a8511e27d6c1..dbac4c03d21a 100644 --- a/drivers/net/xen-netback/rx.c +++ b/drivers/net/xen-netback/rx.c @@ -88,16 +88,19 @@ void xenvif_rx_queue_tail(struct xenvif_queue *queue, struct sk_buff *skb) spin_lock_irqsave(&queue->rx_queue.lock, flags); - if (skb_queue_empty(&queue->rx_queue)) - xenvif_update_needed_slots(queue, skb); - - __skb_queue_tail(&queue->rx_queue, skb); - - queue->rx_queue_len += skb->len; - if (queue->rx_queue_len > queue->rx_queue_max) { + if (queue->rx_queue_len >= queue->rx_queue_max) { struct net_device *dev = queue->vif->dev; netif_tx_stop_queue(netdev_get_tx_queue(dev, queue->id)); + kfree_skb(skb); + queue->vif->dev->stats.rx_dropped++; + } else { + if (skb_queue_empty(&queue->rx_queue)) + xenvif_update_needed_slots(queue, skb); + + __skb_queue_tail(&queue->rx_queue, skb); + + queue->rx_queue_len += skb->len; } spin_unlock_irqrestore(&queue->rx_queue.lock, flags); @@ -147,6 +150,7 @@ static void xenvif_rx_queue_drop_expired(struct xenvif_queue *queue) break; xenvif_rx_dequeue(queue); kfree_skb(skb); + queue->vif->dev->stats.rx_dropped++; } } -- 2.26.2