Skip to content

Commit e9d8b2c

Browse files
Wei Liudavem330
Wei Liu
authored andcommitted
xen-netback: disable rogue vif in kthread context
When netback discovers frontend is sending malformed packet it will disables the interface which serves that frontend. However disabling a network interface involving taking a mutex which cannot be done in softirq context, so we need to defer this process to kthread context. This patch does the following: 1. introduce a flag to indicate the interface is disabled. 2. check that flag in TX path, don't do any work if it's true. 3. check that flag in RX path, turn off that interface if it's true. The reason to disable it in RX path is because RX uses kthread. After this change the behavior of netback is still consistent -- it won't do any TX work for a rogue frontend, and the interface will be eventually turned off. Also change a "continue" to "break" after xenvif_fatal_tx_err, as it doesn't make sense to continue processing packets if frontend is rogue. This is a fix for XSA-90. Reported-by: Török Edwin <[email protected]> Signed-off-by: Wei Liu <[email protected]> Cc: Ian Campbell <[email protected]> Reviewed-by: David Vrabel <[email protected]> Acked-by: Ian Campbell <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent a66132f commit e9d8b2c

File tree

3 files changed

+30
-2
lines changed

3 files changed

+30
-2
lines changed

drivers/net/xen-netback/common.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,11 @@ struct xenvif {
104104
domid_t domid;
105105
unsigned int handle;
106106

107+
/* Is this interface disabled? True when backend discovers
108+
* frontend is rogue.
109+
*/
110+
bool disabled;
111+
107112
/* Use NAPI for guest TX */
108113
struct napi_struct napi;
109114
/* When feature-split-event-channels = 0, tx_irq = rx_irq. */

drivers/net/xen-netback/interface.c

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,15 @@ static int xenvif_poll(struct napi_struct *napi, int budget)
6363
struct xenvif *vif = container_of(napi, struct xenvif, napi);
6464
int work_done;
6565

66+
/* This vif is rogue, we pretend we've there is nothing to do
67+
* for this vif to deschedule it from NAPI. But this interface
68+
* will be turned off in thread context later.
69+
*/
70+
if (unlikely(vif->disabled)) {
71+
napi_complete(napi);
72+
return 0;
73+
}
74+
6675
work_done = xenvif_tx_action(vif, budget);
6776

6877
if (work_done < budget) {
@@ -363,6 +372,8 @@ struct xenvif *xenvif_alloc(struct device *parent, domid_t domid,
363372
vif->ip_csum = 1;
364373
vif->dev = dev;
365374

375+
vif->disabled = false;
376+
366377
vif->credit_bytes = vif->remaining_credit = ~0UL;
367378
vif->credit_usec = 0UL;
368379
init_timer(&vif->credit_timeout);

drivers/net/xen-netback/netback.c

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -711,7 +711,8 @@ static void xenvif_tx_err(struct xenvif *vif,
711711
static void xenvif_fatal_tx_err(struct xenvif *vif)
712712
{
713713
netdev_err(vif->dev, "fatal error; disabling device\n");
714-
xenvif_carrier_off(vif);
714+
vif->disabled = true;
715+
xenvif_kick_thread(vif);
715716
}
716717

717718
static int xenvif_count_requests(struct xenvif *vif,
@@ -1212,7 +1213,7 @@ static unsigned xenvif_tx_build_gops(struct xenvif *vif, int budget)
12121213
vif->tx.sring->req_prod, vif->tx.req_cons,
12131214
XEN_NETIF_TX_RING_SIZE);
12141215
xenvif_fatal_tx_err(vif);
1215-
continue;
1216+
break;
12161217
}
12171218

12181219
work_to_do = RING_HAS_UNCONSUMED_REQUESTS(&vif->tx);
@@ -1808,7 +1809,18 @@ int xenvif_kthread_guest_rx(void *data)
18081809
while (!kthread_should_stop()) {
18091810
wait_event_interruptible(vif->wq,
18101811
rx_work_todo(vif) ||
1812+
vif->disabled ||
18111813
kthread_should_stop());
1814+
1815+
/* This frontend is found to be rogue, disable it in
1816+
* kthread context. Currently this is only set when
1817+
* netback finds out frontend sends malformed packet,
1818+
* but we cannot disable the interface in softirq
1819+
* context so we defer it here.
1820+
*/
1821+
if (unlikely(vif->disabled && netif_carrier_ok(vif->dev)))
1822+
xenvif_carrier_off(vif);
1823+
18121824
if (kthread_should_stop())
18131825
break;
18141826

0 commit comments

Comments
 (0)