| From: Guillaume Nault <g.nault@alphalink.fr> |
| Date: Wed, 10 Jan 2018 16:24:45 +0100 |
| Subject: ppp: unlock all_ppp_mutex before registering device |
| |
| commit 0171c41835591e9aa2e384b703ef9a6ae367c610 upstream. |
| |
| ppp_dev_uninit(), which is the .ndo_uninit() handler of PPP devices, |
| needs to lock pn->all_ppp_mutex. Therefore we mustn't call |
| register_netdevice() with pn->all_ppp_mutex already locked, or we'd |
| deadlock in case register_netdevice() fails and calls .ndo_uninit(). |
| |
| Fortunately, we can unlock pn->all_ppp_mutex before calling |
| register_netdevice(). This lock protects pn->units_idr, which isn't |
| used in the device registration process. |
| |
| However, keeping pn->all_ppp_mutex locked during device registration |
| did ensure that no device in transient state would be published in |
| pn->units_idr. In practice, unlocking it before calling |
| register_netdevice() doesn't change this property: ppp_unit_register() |
| is called with 'ppp_mutex' locked and all searches done in |
| pn->units_idr hold this lock too. |
| |
| Fixes: 8cb775bc0a34 ("ppp: fix device unregistration upon netns deletion") |
| Reported-and-tested-by: syzbot+367889b9c9e279219175@syzkaller.appspotmail.com |
| Signed-off-by: Guillaume Nault <g.nault@alphalink.fr> |
| Signed-off-by: David S. Miller <davem@davemloft.net> |
| [bwh: Backported to 3.16: adjust context] |
| Signed-off-by: Ben Hutchings <ben@decadent.org.uk> |
| --- |
| drivers/net/ppp/ppp_generic.c | 5 +++-- |
| 1 file changed, 3 insertions(+), 2 deletions(-) |
| |
| --- a/drivers/net/ppp/ppp_generic.c |
| +++ b/drivers/net/ppp/ppp_generic.c |
| @@ -2788,6 +2788,8 @@ static struct ppp *ppp_create_interface( |
| ppp->file.index = unit; |
| sprintf(dev->name, "ppp%d", unit); |
| |
| + mutex_unlock(&pn->all_ppp_mutex); |
| + |
| ret = register_netdevice(dev); |
| if (ret != 0) { |
| /* register_netdevice() may have called ppp_dev_init() |
| @@ -2796,6 +2798,7 @@ static struct ppp *ppp_create_interface( |
| */ |
| if (dev->qdisc_tx_busylock) |
| ppp_dev_priv_destructor(dev); |
| + mutex_lock(&pn->all_ppp_mutex); |
| unit_put(&pn->units_idr, unit); |
| netdev_err(ppp->dev, "PPP: couldn't register device %s (%d)\n", |
| dev->name, ret); |
| @@ -2803,7 +2806,6 @@ static struct ppp *ppp_create_interface( |
| } |
| |
| atomic_inc(&ppp_unit_count); |
| - mutex_unlock(&pn->all_ppp_mutex); |
| rtnl_unlock(); |
| |
| *retp = 0; |