|
Jiri Slaby |
8cebe2 |
From: Gao Feng <gfree.wind@vip.163.com>
|
|
Jiri Slaby |
8cebe2 |
Date: Mon, 17 Jul 2017 18:34:42 +0800
|
|
Jiri Slaby |
8cebe2 |
Subject: [PATCH] ppp: Fix false xmit recursion detect with two ppp devices
|
|
Jiri Slaby |
8cebe2 |
References: bnc#1060662
|
|
Thomas Zimmermann |
1d81d2 |
Patch-mainline: v4.12.7
|
|
Jiri Slaby |
8cebe2 |
Git-commit: e5dadc65f9e0177eb649bcd9d333f1ebf871223e
|
|
Jiri Slaby |
8cebe2 |
|
|
Jiri Slaby |
8cebe2 |
[ Upstream commit e5dadc65f9e0177eb649bcd9d333f1ebf871223e ]
|
|
Jiri Slaby |
8cebe2 |
|
|
Jiri Slaby |
8cebe2 |
The global percpu variable ppp_xmit_recursion is used to detect the ppp
|
|
Jiri Slaby |
8cebe2 |
xmit recursion to avoid the deadlock, which is caused by one CPU tries to
|
|
Jiri Slaby |
8cebe2 |
lock the xmit lock twice. But it would report false recursion when one CPU
|
|
Jiri Slaby |
8cebe2 |
wants to send the skb from two different PPP devices, like one L2TP on the
|
|
Jiri Slaby |
8cebe2 |
PPPoE. It is a normal case actually.
|
|
Jiri Slaby |
8cebe2 |
|
|
Jiri Slaby |
8cebe2 |
Now use one percpu member of struct ppp instead of the gloable variable to
|
|
Jiri Slaby |
8cebe2 |
detect the xmit recursion of one ppp device.
|
|
Jiri Slaby |
8cebe2 |
|
|
Jiri Slaby |
8cebe2 |
Fixes: 55454a565836 ("ppp: avoid dealock on recursive xmit")
|
|
Jiri Slaby |
8cebe2 |
Signed-off-by: Gao Feng <gfree.wind@vip.163.com>
|
|
Jiri Slaby |
8cebe2 |
Signed-off-by: Liu Jianying <jianying.liu@ikuai8.com>
|
|
Jiri Slaby |
8cebe2 |
Signed-off-by: David S. Miller <davem@davemloft.net>
|
|
Jiri Slaby |
8cebe2 |
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
|
|
Jiri Slaby |
8cebe2 |
Signed-off-by: Jiri Slaby <jslaby@suse.cz>
|
|
Jiri Slaby |
8cebe2 |
---
|
|
Jiri Slaby |
8cebe2 |
drivers/net/ppp/ppp_generic.c | 30 +++++++++++++++++++++---------
|
|
Jiri Slaby |
8cebe2 |
1 file changed, 21 insertions(+), 9 deletions(-)
|
|
Jiri Slaby |
8cebe2 |
|
|
Jiri Slaby |
8cebe2 |
diff --git a/drivers/net/ppp/ppp_generic.c b/drivers/net/ppp/ppp_generic.c
|
|
Jiri Slaby |
8cebe2 |
index f9c0e62716ea..0d9f776442cb 100644
|
|
Jiri Slaby |
8cebe2 |
--- a/drivers/net/ppp/ppp_generic.c
|
|
Jiri Slaby |
8cebe2 |
+++ b/drivers/net/ppp/ppp_generic.c
|
|
Jiri Slaby |
8cebe2 |
@@ -120,6 +120,7 @@ struct ppp {
|
|
Jiri Slaby |
8cebe2 |
int n_channels; /* how many channels are attached 54 */
|
|
Jiri Slaby |
8cebe2 |
spinlock_t rlock; /* lock for receive side 58 */
|
|
Jiri Slaby |
8cebe2 |
spinlock_t wlock; /* lock for transmit side 5c */
|
|
Jiri Slaby |
8cebe2 |
+ int *xmit_recursion __percpu; /* xmit recursion detect */
|
|
Jiri Slaby |
8cebe2 |
int mru; /* max receive unit 60 */
|
|
Jiri Slaby |
8cebe2 |
unsigned int flags; /* control bits 64 */
|
|
Jiri Slaby |
8cebe2 |
unsigned int xstate; /* transmit state bits 68 */
|
|
Jiri Slaby |
8cebe2 |
@@ -1025,6 +1026,7 @@ static int ppp_dev_configure(struct net *src_net, struct net_device *dev,
|
|
Jiri Slaby |
8cebe2 |
struct ppp *ppp = netdev_priv(dev);
|
|
Jiri Slaby |
8cebe2 |
int indx;
|
|
Jiri Slaby |
8cebe2 |
int err;
|
|
Jiri Slaby |
8cebe2 |
+ int cpu;
|
|
Jiri Slaby |
8cebe2 |
|
|
Jiri Slaby |
8cebe2 |
ppp->dev = dev;
|
|
Jiri Slaby |
8cebe2 |
ppp->ppp_net = src_net;
|
|
Jiri Slaby |
8cebe2 |
@@ -1039,6 +1041,15 @@ static int ppp_dev_configure(struct net *src_net, struct net_device *dev,
|
|
Jiri Slaby |
8cebe2 |
INIT_LIST_HEAD(&ppp->channels);
|
|
Jiri Slaby |
8cebe2 |
spin_lock_init(&ppp->rlock);
|
|
Jiri Slaby |
8cebe2 |
spin_lock_init(&ppp->wlock);
|
|
Jiri Slaby |
8cebe2 |
+
|
|
Jiri Slaby |
8cebe2 |
+ ppp->xmit_recursion = alloc_percpu(int);
|
|
Jiri Slaby |
8cebe2 |
+ if (!ppp->xmit_recursion) {
|
|
Jiri Slaby |
8cebe2 |
+ err = -ENOMEM;
|
|
Jiri Slaby |
8cebe2 |
+ goto err1;
|
|
Jiri Slaby |
8cebe2 |
+ }
|
|
Jiri Slaby |
8cebe2 |
+ for_each_possible_cpu(cpu)
|
|
Jiri Slaby |
8cebe2 |
+ (*per_cpu_ptr(ppp->xmit_recursion, cpu)) = 0;
|
|
Jiri Slaby |
8cebe2 |
+
|
|
Jiri Slaby |
8cebe2 |
#ifdef CONFIG_PPP_MULTILINK
|
|
Jiri Slaby |
8cebe2 |
ppp->minseq = -1;
|
|
Jiri Slaby |
8cebe2 |
skb_queue_head_init(&ppp->mrq);
|
|
Jiri Slaby |
8cebe2 |
@@ -1050,11 +1061,15 @@ static int ppp_dev_configure(struct net *src_net, struct net_device *dev,
|
|
Jiri Slaby |
8cebe2 |
|
|
Jiri Slaby |
8cebe2 |
err = ppp_unit_register(ppp, conf->unit, conf->ifname_is_set);
|
|
Jiri Slaby |
8cebe2 |
if (err < 0)
|
|
Jiri Slaby |
8cebe2 |
- return err;
|
|
Jiri Slaby |
8cebe2 |
+ goto err2;
|
|
Jiri Slaby |
8cebe2 |
|
|
Jiri Slaby |
8cebe2 |
conf->file->private_data = &ppp->file;
|
|
Jiri Slaby |
8cebe2 |
|
|
Jiri Slaby |
8cebe2 |
return 0;
|
|
Jiri Slaby |
8cebe2 |
+err2:
|
|
Jiri Slaby |
8cebe2 |
+ free_percpu(ppp->xmit_recursion);
|
|
Jiri Slaby |
8cebe2 |
+err1:
|
|
Jiri Slaby |
8cebe2 |
+ return err;
|
|
Jiri Slaby |
8cebe2 |
}
|
|
Jiri Slaby |
8cebe2 |
|
|
Jiri Slaby |
8cebe2 |
static const struct nla_policy ppp_nl_policy[IFLA_PPP_MAX + 1] = {
|
|
Jiri Slaby |
8cebe2 |
@@ -1398,18 +1413,16 @@ static void __ppp_xmit_process(struct ppp *ppp)
|
|
Jiri Slaby |
8cebe2 |
ppp_xmit_unlock(ppp);
|
|
Jiri Slaby |
8cebe2 |
}
|
|
Jiri Slaby |
8cebe2 |
|
|
Jiri Slaby |
8cebe2 |
-static DEFINE_PER_CPU(int, ppp_xmit_recursion);
|
|
Jiri Slaby |
8cebe2 |
-
|
|
Jiri Slaby |
8cebe2 |
static void ppp_xmit_process(struct ppp *ppp)
|
|
Jiri Slaby |
8cebe2 |
{
|
|
Jiri Slaby |
8cebe2 |
local_bh_disable();
|
|
Jiri Slaby |
8cebe2 |
|
|
Jiri Slaby |
8cebe2 |
- if (unlikely(__this_cpu_read(ppp_xmit_recursion)))
|
|
Jiri Slaby |
8cebe2 |
+ if (unlikely(*this_cpu_ptr(ppp->xmit_recursion)))
|
|
Jiri Slaby |
8cebe2 |
goto err;
|
|
Jiri Slaby |
8cebe2 |
|
|
Jiri Slaby |
8cebe2 |
- __this_cpu_inc(ppp_xmit_recursion);
|
|
Jiri Slaby |
8cebe2 |
+ (*this_cpu_ptr(ppp->xmit_recursion))++;
|
|
Jiri Slaby |
8cebe2 |
__ppp_xmit_process(ppp);
|
|
Jiri Slaby |
8cebe2 |
- __this_cpu_dec(ppp_xmit_recursion);
|
|
Jiri Slaby |
8cebe2 |
+ (*this_cpu_ptr(ppp->xmit_recursion))--;
|
|
Jiri Slaby |
8cebe2 |
|
|
Jiri Slaby |
8cebe2 |
local_bh_enable();
|
|
Jiri Slaby |
8cebe2 |
|
|
Jiri Slaby |
8cebe2 |
@@ -1903,7 +1916,7 @@ static void __ppp_channel_push(struct channel *pch)
|
|
Jiri Slaby |
8cebe2 |
read_lock_bh(&pch->upl);
|
|
Jiri Slaby |
8cebe2 |
ppp = pch->ppp;
|
|
Jiri Slaby |
8cebe2 |
if (ppp)
|
|
Jiri Slaby |
8cebe2 |
- __ppp_xmit_process(ppp);
|
|
Jiri Slaby |
8cebe2 |
+ ppp_xmit_process(ppp);
|
|
Jiri Slaby |
8cebe2 |
read_unlock_bh(&pch->upl);
|
|
Jiri Slaby |
8cebe2 |
}
|
|
Jiri Slaby |
8cebe2 |
}
|
|
Jiri Slaby |
8cebe2 |
@@ -1912,9 +1925,7 @@ static void ppp_channel_push(struct channel *pch)
|
|
Jiri Slaby |
8cebe2 |
{
|
|
Jiri Slaby |
8cebe2 |
local_bh_disable();
|
|
Jiri Slaby |
8cebe2 |
|
|
Jiri Slaby |
8cebe2 |
- __this_cpu_inc(ppp_xmit_recursion);
|
|
Jiri Slaby |
8cebe2 |
__ppp_channel_push(pch);
|
|
Jiri Slaby |
8cebe2 |
- __this_cpu_dec(ppp_xmit_recursion);
|
|
Jiri Slaby |
8cebe2 |
|
|
Jiri Slaby |
8cebe2 |
local_bh_enable();
|
|
Jiri Slaby |
8cebe2 |
}
|
|
Jiri Slaby |
8cebe2 |
@@ -3055,6 +3066,7 @@ static void ppp_destroy_interface(struct ppp *ppp)
|
|
Jiri Slaby |
8cebe2 |
#endif /* CONFIG_PPP_FILTER */
|
|
Jiri Slaby |
8cebe2 |
|
|
Jiri Slaby |
8cebe2 |
kfree_skb(ppp->xmit_pending);
|
|
Jiri Slaby |
8cebe2 |
+ free_percpu(ppp->xmit_recursion);
|
|
Jiri Slaby |
8cebe2 |
|
|
Jiri Slaby |
8cebe2 |
free_netdev(ppp->dev);
|
|
Jiri Slaby |
8cebe2 |
}
|
|
Jiri Slaby |
8cebe2 |
--
|
|
Jiri Slaby |
8cebe2 |
2.14.2
|
|
Jiri Slaby |
8cebe2 |
|