Received: by 10.213.65.68 with SMTP id h4csp1812904imn; Thu, 29 Mar 2018 11:30:21 -0700 (PDT) X-Google-Smtp-Source: AIpwx49eg/G1xYb68Ud2TUIpfOPrIdzg2Nvgn9tabP4ePB78LdpscGoErsuQ75hq+AnpI1Ng1tUM X-Received: by 10.99.3.216 with SMTP id 207mr6304432pgd.163.1522348221122; Thu, 29 Mar 2018 11:30:21 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1522348221; cv=none; d=google.com; s=arc-20160816; b=wr9Q5avL5XKh5nsEoHF8yNfPESMn7/ctvCwSrU/PDcXR1UVaDHDnyN/qzNkgX+Gu6W 3FzEz+BUfAjB5wQCDFkETvHO1v0TCWZ4vxw24MoT6h1LXUkjl56tlDPQXRdzIsDbP3uQ H/uCtRz2ilQslTuBWyRlIB0t/VGNlyYkEx2MnKxVrITmS2zXVZfXto+jF+E0JyAg7WLl /R2M6geO8PP2l34rBRm0jlOBxjzyDN23T2vmpia4vki8hF18lcqeoMQPXBhS8+8wJpJe pDA0vpRBH5pytfbHqXS1hlyu6K8wGR11rnWhhC4L2GT1VCFNk/ybBgmL/FQPGR1S6sVi 3Dsw== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:mime-version:user-agent:references :in-reply-to:message-id:date:subject:cc:to:from :arc-authentication-results; bh=Z36qr/6kvh5hSDz4EHvb1OP1BwmcRzzJP0FJ+bU7+40=; b=HZXn7hOS/FtsWdGmU9syBQfNTqVxKE87Yl01BwXRQIfqwFYSsHFc0wU7JSVzA5PenG b/EPvodloXWtihQ3QMqDWa9p7Fy83+Pr1yrx7Q0+RInikRZBME7LA6ZdKxhneF8nYjOY VMvEPCFf9qxARMcNOVwy8hJutHLQCHOUAf6JvlNIKyEwQNhzU4u3VVNVvn2q23e8e8Kf AynwZaJQbqgcAbTvzzPYmRlZL6AoqF5RkrBGflpf5eaodw1kx1/2apky8XgYKhrNQzBc qM0pqxB//Acr43v8NQsGpmVCu6yV5sKI5ZGkimujW6MLuIJUfNkrpKFf/55GcLOIRgFc ixLQ== ARC-Authentication-Results: i=1; mx.google.com; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id b3-v6si6578403pld.2.2018.03.29.11.30.06; Thu, 29 Mar 2018 11:30:21 -0700 (PDT) Received-SPF: pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1753219AbeC2SE1 (ORCPT + 99 others); Thu, 29 Mar 2018 14:04:27 -0400 Received: from mail.linuxfoundation.org ([140.211.169.12]:58780 "EHLO mail.linuxfoundation.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1753146AbeC2SEY (ORCPT ); Thu, 29 Mar 2018 14:04:24 -0400 Received: from localhost (LFbn-1-12247-202.w90-92.abo.wanadoo.fr [90.92.61.202]) by mail.linuxfoundation.org (Postfix) with ESMTPSA id 5AB2AC83; Thu, 29 Mar 2018 18:04:23 +0000 (UTC) From: Greg Kroah-Hartman To: linux-kernel@vger.kernel.org Cc: Greg Kroah-Hartman , stable@vger.kernel.org, xu heng , Guillaume Nault , "David S. Miller" Subject: [PATCH 4.14 15/43] ppp: avoid loop in xmit recursion detection code Date: Thu, 29 Mar 2018 20:00:10 +0200 Message-Id: <20180329175731.656227777@linuxfoundation.org> X-Mailer: git-send-email 2.16.3 In-Reply-To: <20180329175730.190353692@linuxfoundation.org> References: <20180329175730.190353692@linuxfoundation.org> User-Agent: quilt/0.65 X-stable: review MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org 4.14-stable review patch. If anyone has any objections, please let me know. ------------------ From: Guillaume Nault [ Upstream commit 6d066734e9f09cdea4a3b9cb76136db3f29cfb02 ] 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 Fixes: 55454a565836 ("ppp: avoid dealock on recursive xmit") Signed-off-by: Guillaume Nault Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- drivers/net/ppp/ppp_generic.c | 26 ++++++++++++++------------ 1 file changed, 14 insertions(+), 12 deletions(-) --- a/drivers/net/ppp/ppp_generic.c +++ b/drivers/net/ppp/ppp_generic.c @@ -256,7 +256,7 @@ struct ppp_net { /* Prototypes. */ static int ppp_unattached_ioctl(struct net *net, struct ppp_file *pf, struct file *file, unsigned int cmd, unsigned long arg); -static void ppp_xmit_process(struct ppp *ppp); +static void ppp_xmit_process(struct ppp *ppp, struct sk_buff *skb); static void ppp_send_frame(struct ppp *ppp, struct sk_buff *skb); static void ppp_push(struct ppp *ppp); static void ppp_channel_push(struct channel *pch); @@ -512,13 +512,12 @@ static ssize_t ppp_write(struct file *fi goto out; } - skb_queue_tail(&pf->xq, skb); - switch (pf->kind) { case INTERFACE: - ppp_xmit_process(PF_TO_PPP(pf)); + ppp_xmit_process(PF_TO_PPP(pf), skb); break; case CHANNEL: + skb_queue_tail(&pf->xq, skb); ppp_channel_push(PF_TO_CHANNEL(pf)); break; } @@ -1264,8 +1263,8 @@ ppp_start_xmit(struct sk_buff *skb, stru put_unaligned_be16(proto, pp); skb_scrub_packet(skb, !net_eq(ppp->ppp_net, dev_net(dev))); - skb_queue_tail(&ppp->file.xq, skb); - ppp_xmit_process(ppp); + ppp_xmit_process(ppp, skb); + return NETDEV_TX_OK; outf: @@ -1417,13 +1416,14 @@ static void ppp_setup(struct net_device */ /* Called to do any work queued up on the transmit side that can now be done */ -static void __ppp_xmit_process(struct ppp *ppp) +static void __ppp_xmit_process(struct ppp *ppp, struct sk_buff *skb) { - struct sk_buff *skb; - ppp_xmit_lock(ppp); if (!ppp->closing) { ppp_push(ppp); + + if (skb) + skb_queue_tail(&ppp->file.xq, skb); while (!ppp->xmit_pending && (skb = skb_dequeue(&ppp->file.xq))) ppp_send_frame(ppp, skb); @@ -1437,7 +1437,7 @@ static void __ppp_xmit_process(struct pp ppp_xmit_unlock(ppp); } -static void ppp_xmit_process(struct ppp *ppp) +static void ppp_xmit_process(struct ppp *ppp, struct sk_buff *skb) { local_bh_disable(); @@ -1445,7 +1445,7 @@ static void ppp_xmit_process(struct ppp goto err; (*this_cpu_ptr(ppp->xmit_recursion))++; - __ppp_xmit_process(ppp); + __ppp_xmit_process(ppp, skb); (*this_cpu_ptr(ppp->xmit_recursion))--; local_bh_enable(); @@ -1455,6 +1455,8 @@ static void ppp_xmit_process(struct ppp err: local_bh_enable(); + kfree_skb(skb); + if (net_ratelimit()) netdev_err(ppp->dev, "recursion detected\n"); } @@ -1939,7 +1941,7 @@ static void __ppp_channel_push(struct ch if (skb_queue_empty(&pch->file.xq)) { ppp = pch->ppp; if (ppp) - __ppp_xmit_process(ppp); + __ppp_xmit_process(ppp, NULL); } }