Skip to content

Commit 6032046

Browse files
committed
xen/netback: fix rx queue stall detection
Commit 1d5d485 ("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 part of XSA-392 Fixes: 1d5d485 ("xen-netback: require fewer guest Rx slots when not using GSO") Signed-off-by: Juergen Gross <jgross@suse.com> Reviewed-by: Jan Beulich <jbeulich@suse.com>
1 parent fe41518 commit 6032046

2 files changed

Lines changed: 42 additions & 24 deletions

File tree

drivers/net/xen-netback/common.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -203,6 +203,7 @@ struct xenvif_queue { /* Per-queue data for xenvif */
203203
unsigned int rx_queue_max;
204204
unsigned int rx_queue_len;
205205
unsigned long last_rx_time;
206+
unsigned int rx_slots_needed;
206207
bool stalled;
207208

208209
struct xenvif_copy_state rx_copy;

drivers/net/xen-netback/rx.c

Lines changed: 41 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -33,28 +33,36 @@
3333
#include <xen/xen.h>
3434
#include <xen/events.h>
3535

36-
static bool xenvif_rx_ring_slots_available(struct xenvif_queue *queue)
36+
/*
37+
* Update the needed ring page slots for the first SKB queued.
38+
* Note that any call sequence outside the RX thread calling this function
39+
* needs to wake up the RX thread via a call of xenvif_kick_thread()
40+
* afterwards in order to avoid a race with putting the thread to sleep.
41+
*/
42+
static void xenvif_update_needed_slots(struct xenvif_queue *queue,
43+
const struct sk_buff *skb)
3744
{
38-
RING_IDX prod, cons;
39-
struct sk_buff *skb;
40-
int needed;
41-
unsigned long flags;
42-
43-
spin_lock_irqsave(&queue->rx_queue.lock, flags);
45+
unsigned int needed = 0;
4446

45-
skb = skb_peek(&queue->rx_queue);
46-
if (!skb) {
47-
spin_unlock_irqrestore(&queue->rx_queue.lock, flags);
48-
return false;
47+
if (skb) {
48+
needed = DIV_ROUND_UP(skb->len, XEN_PAGE_SIZE);
49+
if (skb_is_gso(skb))
50+
needed++;
51+
if (skb->sw_hash)
52+
needed++;
4953
}
5054

51-
needed = DIV_ROUND_UP(skb->len, XEN_PAGE_SIZE);
52-
if (skb_is_gso(skb))
53-
needed++;
54-
if (skb->sw_hash)
55-
needed++;
55+
WRITE_ONCE(queue->rx_slots_needed, needed);
56+
}
5657

57-
spin_unlock_irqrestore(&queue->rx_queue.lock, flags);
58+
static bool xenvif_rx_ring_slots_available(struct xenvif_queue *queue)
59+
{
60+
RING_IDX prod, cons;
61+
unsigned int needed;
62+
63+
needed = READ_ONCE(queue->rx_slots_needed);
64+
if (!needed)
65+
return false;
5866

5967
do {
6068
prod = queue->rx.sring->req_prod;
@@ -80,6 +88,9 @@ void xenvif_rx_queue_tail(struct xenvif_queue *queue, struct sk_buff *skb)
8088

8189
spin_lock_irqsave(&queue->rx_queue.lock, flags);
8290

91+
if (skb_queue_empty(&queue->rx_queue))
92+
xenvif_update_needed_slots(queue, skb);
93+
8394
__skb_queue_tail(&queue->rx_queue, skb);
8495

8596
queue->rx_queue_len += skb->len;
@@ -100,6 +111,8 @@ static struct sk_buff *xenvif_rx_dequeue(struct xenvif_queue *queue)
100111

101112
skb = __skb_dequeue(&queue->rx_queue);
102113
if (skb) {
114+
xenvif_update_needed_slots(queue, skb_peek(&queue->rx_queue));
115+
103116
queue->rx_queue_len -= skb->len;
104117
if (queue->rx_queue_len < queue->rx_queue_max) {
105118
struct netdev_queue *txq;
@@ -487,27 +500,31 @@ void xenvif_rx_action(struct xenvif_queue *queue)
487500
xenvif_rx_copy_flush(queue);
488501
}
489502

490-
static bool xenvif_rx_queue_stalled(struct xenvif_queue *queue)
503+
static RING_IDX xenvif_rx_queue_slots(const struct xenvif_queue *queue)
491504
{
492505
RING_IDX prod, cons;
493506

494507
prod = queue->rx.sring->req_prod;
495508
cons = queue->rx.req_cons;
496509

510+
return prod - cons;
511+
}
512+
513+
static bool xenvif_rx_queue_stalled(const struct xenvif_queue *queue)
514+
{
515+
unsigned int needed = READ_ONCE(queue->rx_slots_needed);
516+
497517
return !queue->stalled &&
498-
prod - cons < 1 &&
518+
xenvif_rx_queue_slots(queue) < needed &&
499519
time_after(jiffies,
500520
queue->last_rx_time + queue->vif->stall_timeout);
501521
}
502522

503523
static bool xenvif_rx_queue_ready(struct xenvif_queue *queue)
504524
{
505-
RING_IDX prod, cons;
506-
507-
prod = queue->rx.sring->req_prod;
508-
cons = queue->rx.req_cons;
525+
unsigned int needed = READ_ONCE(queue->rx_slots_needed);
509526

510-
return queue->stalled && prod - cons >= 1;
527+
return queue->stalled && xenvif_rx_queue_slots(queue) >= needed;
511528
}
512529

513530
bool xenvif_have_rx_work(struct xenvif_queue *queue, bool test_kthread)

0 commit comments

Comments
 (0)