Skip to content

Commit 6d06673

Browse files
Guillaume Naultdavem330
authored andcommitted
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 <[email protected]> Fixes: 55454a5 ("ppp: avoid dealock on recursive xmit") Signed-off-by: Guillaume Nault <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent 8936ef7 commit 6d06673

File tree

1 file changed

+14
-12
lines changed

1 file changed

+14
-12
lines changed

drivers/net/ppp/ppp_generic.c

Lines changed: 14 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -257,7 +257,7 @@ struct ppp_net {
257257
/* Prototypes. */
258258
static int ppp_unattached_ioctl(struct net *net, struct ppp_file *pf,
259259
struct file *file, unsigned int cmd, unsigned long arg);
260-
static void ppp_xmit_process(struct ppp *ppp);
260+
static void ppp_xmit_process(struct ppp *ppp, struct sk_buff *skb);
261261
static void ppp_send_frame(struct ppp *ppp, struct sk_buff *skb);
262262
static void ppp_push(struct ppp *ppp);
263263
static void ppp_channel_push(struct channel *pch);
@@ -513,13 +513,12 @@ static ssize_t ppp_write(struct file *file, const char __user *buf,
513513
goto out;
514514
}
515515

516-
skb_queue_tail(&pf->xq, skb);
517-
518516
switch (pf->kind) {
519517
case INTERFACE:
520-
ppp_xmit_process(PF_TO_PPP(pf));
518+
ppp_xmit_process(PF_TO_PPP(pf), skb);
521519
break;
522520
case CHANNEL:
521+
skb_queue_tail(&pf->xq, skb);
523522
ppp_channel_push(PF_TO_CHANNEL(pf));
524523
break;
525524
}
@@ -1267,8 +1266,8 @@ ppp_start_xmit(struct sk_buff *skb, struct net_device *dev)
12671266
put_unaligned_be16(proto, pp);
12681267

12691268
skb_scrub_packet(skb, !net_eq(ppp->ppp_net, dev_net(dev)));
1270-
skb_queue_tail(&ppp->file.xq, skb);
1271-
ppp_xmit_process(ppp);
1269+
ppp_xmit_process(ppp, skb);
1270+
12721271
return NETDEV_TX_OK;
12731272

12741273
outf:
@@ -1420,13 +1419,14 @@ static void ppp_setup(struct net_device *dev)
14201419
*/
14211420

14221421
/* Called to do any work queued up on the transmit side that can now be done */
1423-
static void __ppp_xmit_process(struct ppp *ppp)
1422+
static void __ppp_xmit_process(struct ppp *ppp, struct sk_buff *skb)
14241423
{
1425-
struct sk_buff *skb;
1426-
14271424
ppp_xmit_lock(ppp);
14281425
if (!ppp->closing) {
14291426
ppp_push(ppp);
1427+
1428+
if (skb)
1429+
skb_queue_tail(&ppp->file.xq, skb);
14301430
while (!ppp->xmit_pending &&
14311431
(skb = skb_dequeue(&ppp->file.xq)))
14321432
ppp_send_frame(ppp, skb);
@@ -1440,15 +1440,15 @@ static void __ppp_xmit_process(struct ppp *ppp)
14401440
ppp_xmit_unlock(ppp);
14411441
}
14421442

1443-
static void ppp_xmit_process(struct ppp *ppp)
1443+
static void ppp_xmit_process(struct ppp *ppp, struct sk_buff *skb)
14441444
{
14451445
local_bh_disable();
14461446

14471447
if (unlikely(*this_cpu_ptr(ppp->xmit_recursion)))
14481448
goto err;
14491449

14501450
(*this_cpu_ptr(ppp->xmit_recursion))++;
1451-
__ppp_xmit_process(ppp);
1451+
__ppp_xmit_process(ppp, skb);
14521452
(*this_cpu_ptr(ppp->xmit_recursion))--;
14531453

14541454
local_bh_enable();
@@ -1458,6 +1458,8 @@ static void ppp_xmit_process(struct ppp *ppp)
14581458
err:
14591459
local_bh_enable();
14601460

1461+
kfree_skb(skb);
1462+
14611463
if (net_ratelimit())
14621464
netdev_err(ppp->dev, "recursion detected\n");
14631465
}
@@ -1942,7 +1944,7 @@ static void __ppp_channel_push(struct channel *pch)
19421944
if (skb_queue_empty(&pch->file.xq)) {
19431945
ppp = pch->ppp;
19441946
if (ppp)
1945-
__ppp_xmit_process(ppp);
1947+
__ppp_xmit_process(ppp, NULL);
19461948
}
19471949
}
19481950

0 commit comments

Comments
 (0)