Skip to content

Commit 8cb775b

Browse files
Guillaume Naultdavem330
authored andcommitted
ppp: fix device unregistration upon netns deletion
PPP devices may get automatically unregistered when their network namespace is getting removed. This happens if the ppp control plane daemon (e.g. pppd) exits while it is the last user of this namespace. This leads to several races: * ppp_exit_net() may destroy the per namespace idr (pn->units_idr) before all file descriptors were released. Successive ppp_release() calls may then cleanup PPP devices with ppp_shutdown_interface() and try to use the already destroyed idr. * Automatic device unregistration may also happen before the ppp_release() call for that device gets executed. Once called on the file owning the device, ppp_release() will then clean it up and try to unregister it a second time. To fix these issues, operations defined in ppp_shutdown_interface() are moved to the PPP device's ndo_uninit() callback. This allows PPP devices to be properly cleaned up by unregister_netdev() and friends. So checking for ppp->owner is now an accurate test to decide if a PPP device should be unregistered. Setting ppp->owner is done in ppp_create_interface(), before device registration, in order to avoid unprotected modification of this field. Finally, ppp_exit_net() now starts by unregistering all remaining PPP devices to ensure that none will get unregistered after the call to idr_destroy(). Signed-off-by: Guillaume Nault <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent 11e122c commit 8cb775b

File tree

1 file changed

+42
-36
lines changed

1 file changed

+42
-36
lines changed

drivers/net/ppp/ppp_generic.c

Lines changed: 42 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -269,9 +269,9 @@ static void ppp_ccp_peek(struct ppp *ppp, struct sk_buff *skb, int inbound);
269269
static void ppp_ccp_closed(struct ppp *ppp);
270270
static struct compressor *find_compressor(int type);
271271
static void ppp_get_stats(struct ppp *ppp, struct ppp_stats *st);
272-
static struct ppp *ppp_create_interface(struct net *net, int unit, int *retp);
272+
static struct ppp *ppp_create_interface(struct net *net, int unit,
273+
struct file *file, int *retp);
273274
static void init_ppp_file(struct ppp_file *pf, int kind);
274-
static void ppp_shutdown_interface(struct ppp *ppp);
275275
static void ppp_destroy_interface(struct ppp *ppp);
276276
static struct ppp *ppp_find_unit(struct ppp_net *pn, int unit);
277277
static struct channel *ppp_find_channel(struct ppp_net *pn, int unit);
@@ -392,8 +392,10 @@ static int ppp_release(struct inode *unused, struct file *file)
392392
file->private_data = NULL;
393393
if (pf->kind == INTERFACE) {
394394
ppp = PF_TO_PPP(pf);
395+
rtnl_lock();
395396
if (file == ppp->owner)
396-
ppp_shutdown_interface(ppp);
397+
unregister_netdevice(ppp->dev);
398+
rtnl_unlock();
397399
}
398400
if (atomic_dec_and_test(&pf->refcnt)) {
399401
switch (pf->kind) {
@@ -593,8 +595,10 @@ static long ppp_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
593595
mutex_lock(&ppp_mutex);
594596
if (pf->kind == INTERFACE) {
595597
ppp = PF_TO_PPP(pf);
598+
rtnl_lock();
596599
if (file == ppp->owner)
597-
ppp_shutdown_interface(ppp);
600+
unregister_netdevice(ppp->dev);
601+
rtnl_unlock();
598602
}
599603
if (atomic_long_read(&file->f_count) < 2) {
600604
ppp_release(NULL, file);
@@ -838,11 +842,10 @@ static int ppp_unattached_ioctl(struct net *net, struct ppp_file *pf,
838842
/* Create a new ppp unit */
839843
if (get_user(unit, p))
840844
break;
841-
ppp = ppp_create_interface(net, unit, &err);
845+
ppp = ppp_create_interface(net, unit, file, &err);
842846
if (!ppp)
843847
break;
844848
file->private_data = &ppp->file;
845-
ppp->owner = file;
846849
err = -EFAULT;
847850
if (put_user(ppp->file.index, p))
848851
break;
@@ -916,6 +919,16 @@ static __net_init int ppp_init_net(struct net *net)
916919
static __net_exit void ppp_exit_net(struct net *net)
917920
{
918921
struct ppp_net *pn = net_generic(net, ppp_net_id);
922+
struct ppp *ppp;
923+
LIST_HEAD(list);
924+
int id;
925+
926+
rtnl_lock();
927+
idr_for_each_entry(&pn->units_idr, ppp, id)
928+
unregister_netdevice_queue(ppp->dev, &list);
929+
930+
unregister_netdevice_many(&list);
931+
rtnl_unlock();
919932

920933
idr_destroy(&pn->units_idr);
921934
}
@@ -1088,8 +1101,28 @@ static int ppp_dev_init(struct net_device *dev)
10881101
return 0;
10891102
}
10901103

1104+
static void ppp_dev_uninit(struct net_device *dev)
1105+
{
1106+
struct ppp *ppp = netdev_priv(dev);
1107+
struct ppp_net *pn = ppp_pernet(ppp->ppp_net);
1108+
1109+
ppp_lock(ppp);
1110+
ppp->closing = 1;
1111+
ppp_unlock(ppp);
1112+
1113+
mutex_lock(&pn->all_ppp_mutex);
1114+
unit_put(&pn->units_idr, ppp->file.index);
1115+
mutex_unlock(&pn->all_ppp_mutex);
1116+
1117+
ppp->owner = NULL;
1118+
1119+
ppp->file.dead = 1;
1120+
wake_up_interruptible(&ppp->file.rwait);
1121+
}
1122+
10911123
static const struct net_device_ops ppp_netdev_ops = {
10921124
.ndo_init = ppp_dev_init,
1125+
.ndo_uninit = ppp_dev_uninit,
10931126
.ndo_start_xmit = ppp_start_xmit,
10941127
.ndo_do_ioctl = ppp_net_ioctl,
10951128
.ndo_get_stats64 = ppp_get_stats64,
@@ -2667,8 +2700,8 @@ ppp_get_stats(struct ppp *ppp, struct ppp_stats *st)
26672700
* or if there is already a unit with the requested number.
26682701
* unit == -1 means allocate a new number.
26692702
*/
2670-
static struct ppp *
2671-
ppp_create_interface(struct net *net, int unit, int *retp)
2703+
static struct ppp *ppp_create_interface(struct net *net, int unit,
2704+
struct file *file, int *retp)
26722705
{
26732706
struct ppp *ppp;
26742707
struct ppp_net *pn;
@@ -2688,6 +2721,7 @@ ppp_create_interface(struct net *net, int unit, int *retp)
26882721
ppp->mru = PPP_MRU;
26892722
init_ppp_file(&ppp->file, INTERFACE);
26902723
ppp->file.hdrlen = PPP_HDRLEN - 2; /* don't count proto bytes */
2724+
ppp->owner = file;
26912725
for (i = 0; i < NUM_NP; ++i)
26922726
ppp->npmode[i] = NPMODE_PASS;
26932727
INIT_LIST_HEAD(&ppp->channels);
@@ -2775,34 +2809,6 @@ init_ppp_file(struct ppp_file *pf, int kind)
27752809
init_waitqueue_head(&pf->rwait);
27762810
}
27772811

2778-
/*
2779-
* Take down a ppp interface unit - called when the owning file
2780-
* (the one that created the unit) is closed or detached.
2781-
*/
2782-
static void ppp_shutdown_interface(struct ppp *ppp)
2783-
{
2784-
struct ppp_net *pn;
2785-
2786-
pn = ppp_pernet(ppp->ppp_net);
2787-
mutex_lock(&pn->all_ppp_mutex);
2788-
2789-
/* This will call dev_close() for us. */
2790-
ppp_lock(ppp);
2791-
if (!ppp->closing) {
2792-
ppp->closing = 1;
2793-
ppp_unlock(ppp);
2794-
unregister_netdev(ppp->dev);
2795-
unit_put(&pn->units_idr, ppp->file.index);
2796-
} else
2797-
ppp_unlock(ppp);
2798-
2799-
ppp->file.dead = 1;
2800-
ppp->owner = NULL;
2801-
wake_up_interruptible(&ppp->file.rwait);
2802-
2803-
mutex_unlock(&pn->all_ppp_mutex);
2804-
}
2805-
28062812
/*
28072813
* Free the memory used by a ppp unit. This is only called once
28082814
* there are no channels connected to the unit and no file structs

0 commit comments

Comments
 (0)