aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorGuillaume Nault <g.nault@alphalink.fr>2018-03-20 11:49:26 -0400
committerDavid S. Miller <davem@davemloft.net>2018-03-22 12:35:18 -0400
commit6d066734e9f09cdea4a3b9cb76136db3f29cfb02 (patch)
tree68c22189393640a701842c65d32ffd06d0346012 /drivers
parent8936ef7604c11b5d701580d779e0f5684abc7b68 (diff)
ppp: avoid loop in xmit recursion detection code
We already detect situations where a PPP channel sends packets back to its upper PPP device. While this is enough to avoid deadlocking on xmit locks, this doesn't prevent packets from looping between the channel and the unit. The problem is that ppp_start_xmit() enqueues packets in ppp->file.xq before checking for xmit recursion. Therefore, __ppp_xmit_process() might dequeue a packet from ppp->file.xq and send it on the channel which, in turn, loops it back on the unit. Then ppp_start_xmit() queues the packet back to ppp->file.xq and __ppp_xmit_process() picks it up and sends it again through the channel. Therefore, the packet will loop between __ppp_xmit_process() and ppp_start_xmit() until some other part of the xmit path drops it. For L2TP, we rapidly fill the skb's headroom and pppol2tp_xmit() drops the packet after a few iterations. But PPTP reallocates the headroom if necessary, letting the loop run and exhaust the machine resources (as reported in https://bugzilla.kernel.org/show_bug.cgi?id=199109). Fix this by letting __ppp_xmit_process() enqueue the skb to ppp->file.xq, so that we can check for recursion before adding it to the queue. Now ppp_xmit_process() can drop the packet when recursion is detected. __ppp_channel_push() is a bit special. It calls __ppp_xmit_process() without having any actual packet to send. This is used by ppp_output_wakeup() to re-enable transmission on the parent unit (for implementations like ppp_async.c, where the .start_xmit() function might not consume the skb, leaving it in ppp->xmit_pending and disabling transmission). Therefore, __ppp_xmit_process() needs to handle the case where skb is NULL, dequeuing as many packets as possible from ppp->file.xq. Reported-by: xu heng <xuheng333@zoho.com> Fixes: 55454a565836 ("ppp: avoid dealock on recursive xmit") Signed-off-by: Guillaume Nault <g.nault@alphalink.fr> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/net/ppp/ppp_generic.c26
1 files changed, 14 insertions, 12 deletions
diff --git a/drivers/net/ppp/ppp_generic.c b/drivers/net/ppp/ppp_generic.c
index fa2a9bdd1866..da1937832c99 100644
--- a/drivers/net/ppp/ppp_generic.c
+++ b/drivers/net/ppp/ppp_generic.c
@@ -257,7 +257,7 @@ struct ppp_net {
257/* Prototypes. */ 257/* Prototypes. */
258static int ppp_unattached_ioctl(struct net *net, struct ppp_file *pf, 258static int ppp_unattached_ioctl(struct net *net, struct ppp_file *pf,
259 struct file *file, unsigned int cmd, unsigned long arg); 259 struct file *file, unsigned int cmd, unsigned long arg);
260static void ppp_xmit_process(struct ppp *ppp); 260static void ppp_xmit_process(struct ppp *ppp, struct sk_buff *skb);
261static void ppp_send_frame(struct ppp *ppp, struct sk_buff *skb); 261static void ppp_send_frame(struct ppp *ppp, struct sk_buff *skb);
262static void ppp_push(struct ppp *ppp); 262static void ppp_push(struct ppp *ppp);
263static void ppp_channel_push(struct channel *pch); 263static void ppp_channel_push(struct channel *pch);
@@ -513,13 +513,12 @@ static ssize_t ppp_write(struct file *file, const char __user *buf,
513 goto out; 513 goto out;
514 } 514 }
515 515
516 skb_queue_tail(&pf->xq, skb);
517
518 switch (pf->kind) { 516 switch (pf->kind) {
519 case INTERFACE: 517 case INTERFACE:
520 ppp_xmit_process(PF_TO_PPP(pf)); 518 ppp_xmit_process(PF_TO_PPP(pf), skb);
521 break; 519 break;
522 case CHANNEL: 520 case CHANNEL:
521 skb_queue_tail(&pf->xq, skb);
523 ppp_channel_push(PF_TO_CHANNEL(pf)); 522 ppp_channel_push(PF_TO_CHANNEL(pf));
524 break; 523 break;
525 } 524 }
@@ -1267,8 +1266,8 @@ ppp_start_xmit(struct sk_buff *skb, struct net_device *dev)
1267 put_unaligned_be16(proto, pp); 1266 put_unaligned_be16(proto, pp);
1268 1267
1269 skb_scrub_packet(skb, !net_eq(ppp->ppp_net, dev_net(dev))); 1268 skb_scrub_packet(skb, !net_eq(ppp->ppp_net, dev_net(dev)));
1270 skb_queue_tail(&ppp->file.xq, skb); 1269 ppp_xmit_process(ppp, skb);
1271 ppp_xmit_process(ppp); 1270
1272 return NETDEV_TX_OK; 1271 return NETDEV_TX_OK;
1273 1272
1274 outf: 1273 outf:
@@ -1420,13 +1419,14 @@ static void ppp_setup(struct net_device *dev)
1420 */ 1419 */
1421 1420
1422/* Called to do any work queued up on the transmit side that can now be done */ 1421/* Called to do any work queued up on the transmit side that can now be done */
1423static void __ppp_xmit_process(struct ppp *ppp) 1422static void __ppp_xmit_process(struct ppp *ppp, struct sk_buff *skb)
1424{ 1423{
1425 struct sk_buff *skb;
1426
1427 ppp_xmit_lock(ppp); 1424 ppp_xmit_lock(ppp);
1428 if (!ppp->closing) { 1425 if (!ppp->closing) {
1429 ppp_push(ppp); 1426 ppp_push(ppp);
1427
1428 if (skb)
1429 skb_queue_tail(&ppp->file.xq, skb);
1430 while (!ppp->xmit_pending && 1430 while (!ppp->xmit_pending &&
1431 (skb = skb_dequeue(&ppp->file.xq))) 1431 (skb = skb_dequeue(&ppp->file.xq)))
1432 ppp_send_frame(ppp, skb); 1432 ppp_send_frame(ppp, skb);
@@ -1440,7 +1440,7 @@ static void __ppp_xmit_process(struct ppp *ppp)
1440 ppp_xmit_unlock(ppp); 1440 ppp_xmit_unlock(ppp);
1441} 1441}
1442 1442
1443static void ppp_xmit_process(struct ppp *ppp) 1443static void ppp_xmit_process(struct ppp *ppp, struct sk_buff *skb)
1444{ 1444{
1445 local_bh_disable(); 1445 local_bh_disable();
1446 1446
@@ -1448,7 +1448,7 @@ static void ppp_xmit_process(struct ppp *ppp)
1448 goto err; 1448 goto err;
1449 1449
1450 (*this_cpu_ptr(ppp->xmit_recursion))++; 1450 (*this_cpu_ptr(ppp->xmit_recursion))++;
1451 __ppp_xmit_process(ppp); 1451 __ppp_xmit_process(ppp, skb);
1452 (*this_cpu_ptr(ppp->xmit_recursion))--; 1452 (*this_cpu_ptr(ppp->xmit_recursion))--;
1453 1453
1454 local_bh_enable(); 1454 local_bh_enable();
@@ -1458,6 +1458,8 @@ static void ppp_xmit_process(struct ppp *ppp)
1458err: 1458err:
1459 local_bh_enable(); 1459 local_bh_enable();
1460 1460
1461 kfree_skb(skb);
1462
1461 if (net_ratelimit()) 1463 if (net_ratelimit())
1462 netdev_err(ppp->dev, "recursion detected\n"); 1464 netdev_err(ppp->dev, "recursion detected\n");
1463} 1465}
@@ -1942,7 +1944,7 @@ static void __ppp_channel_push(struct channel *pch)
1942 if (skb_queue_empty(&pch->file.xq)) { 1944 if (skb_queue_empty(&pch->file.xq)) {
1943 ppp = pch->ppp; 1945 ppp = pch->ppp;
1944 if (ppp) 1946 if (ppp)
1945 __ppp_xmit_process(ppp); 1947 __ppp_xmit_process(ppp, NULL);
1946 } 1948 }
1947} 1949}
1948 1950