xen/netback: don't call kfree_skb() with interrupts disabled
authorJuergen Gross <jgross@suse.com>
Tue, 6 Dec 2022 07:54:24 +0000 (08:54 +0100)
committerSalvatore Bonaccorso <carnil@debian.org>
Tue, 13 Dec 2022 20:46:50 +0000 (20:46 +0000)
Origin: https://git.kernel.org/linus/74e7e1efdad45580cc3839f2a155174cf158f9b5
Bug-Debian-Security: https://security-tracker.debian.org/tracker/CVE-2022-42329
Bug-Debian-Security: https://security-tracker.debian.org/tracker/CVE-2022-42328

It is not allowed to call kfree_skb() from hardware interrupt
context or with interrupts being disabled. So remove kfree_skb()
from the spin_lock_irqsave() section and use the already existing
"drop" label in xenvif_start_xmit() for dropping the SKB. At the
same time replace the dev_kfree_skb() call there with a call of
dev_kfree_skb_any(), as xenvif_start_xmit() can be called with
disabled interrupts.

This is XSA-424 / CVE-2022-42328 / CVE-2022-42329.

Fixes: be81992f9086 ("xen/netback: don't queue unlimited number of packages")
Reported-by: Yang Yingliang <yangyingliang@huawei.com>
Signed-off-by: Juergen Gross <jgross@suse.com>
Reviewed-by: Jan Beulich <jbeulich@suse.com>
Signed-off-by: Juergen Gross <jgross@suse.com>
Gbp-Pq: Topic bugfix/all
Gbp-Pq: Name xen-netback-don-t-call-kfree_skb-with-interrupts-dis.patch

drivers/net/xen-netback/common.h
drivers/net/xen-netback/interface.c
drivers/net/xen-netback/rx.c

index 945647128c0e576627f31badbc66db7b537ce51d..1ba974969216419ee29a3c4a746bd22d1f8df1b1 100644 (file)
@@ -386,7 +386,7 @@ int xenvif_dealloc_kthread(void *data);
 irqreturn_t xenvif_ctrl_irq_fn(int irq, void *data);
 
 bool xenvif_have_rx_work(struct xenvif_queue *queue, bool test_kthread);
-void xenvif_rx_queue_tail(struct xenvif_queue *queue, struct sk_buff *skb);
+bool xenvif_rx_queue_tail(struct xenvif_queue *queue, struct sk_buff *skb);
 
 void xenvif_carrier_on(struct xenvif *vif);
 
index 645a804ab78877e78e20842ee99982ff8ca26cd8..97cf5bc48902a211db932de9089bd13bc0a7ac56 100644 (file)
@@ -255,14 +255,16 @@ xenvif_start_xmit(struct sk_buff *skb, struct net_device *dev)
        if (vif->hash.alg == XEN_NETIF_CTRL_HASH_ALGORITHM_NONE)
                skb_clear_hash(skb);
 
-       xenvif_rx_queue_tail(queue, skb);
+       if (!xenvif_rx_queue_tail(queue, skb))
+               goto drop;
+
        xenvif_kick_thread(queue);
 
        return NETDEV_TX_OK;
 
  drop:
        vif->dev->stats.tx_dropped++;
-       dev_kfree_skb(skb);
+       dev_kfree_skb_any(skb);
        return NETDEV_TX_OK;
 }
 
index 9327621771109aa929c44c77e079b3f873426653..0ba754ebc5baafaf3f164c80934244e49263a45c 100644 (file)
@@ -82,9 +82,10 @@ static bool xenvif_rx_ring_slots_available(struct xenvif_queue *queue)
        return false;
 }
 
-void xenvif_rx_queue_tail(struct xenvif_queue *queue, struct sk_buff *skb)
+bool xenvif_rx_queue_tail(struct xenvif_queue *queue, struct sk_buff *skb)
 {
        unsigned long flags;
+       bool ret = true;
 
        spin_lock_irqsave(&queue->rx_queue.lock, flags);
 
@@ -92,8 +93,7 @@ void xenvif_rx_queue_tail(struct xenvif_queue *queue, struct sk_buff *skb)
                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++;
+               ret = false;
        } else {
                if (skb_queue_empty(&queue->rx_queue))
                        xenvif_update_needed_slots(queue, skb);
@@ -104,6 +104,8 @@ void xenvif_rx_queue_tail(struct xenvif_queue *queue, struct sk_buff *skb)
        }
 
        spin_unlock_irqrestore(&queue->rx_queue.lock, flags);
+
+       return ret;
 }
 
 static struct sk_buff *xenvif_rx_dequeue(struct xenvif_queue *queue)