Let ppp_unattached_ioctl() lock ppp_mutex only when needed. For PPPIOCATTACH and PPPIOCATTCHAN, we just need to lock ppp_mutex before all_ppp_mutex/all_channels_lock (to keep lock ordering) and to take care of the -ENOTTY error code when file->private_data is not NULL. For PPPIOCNEWUNIT, ppp_mutex is pushed further down in ppp_create_interface() and is held right before rtnl_lock. The goal is to eventually lock ppp_mutex after rtnl_lock, so that PPP device creation can be done inside a rtnetlink function handler. While there, remove unused ppp_file argument from ppp_unattached_ioctl() prototype. Signed-off-by: Guillaume Nault <g.nault@xxxxxxxxxxxx> --- drivers/net/ppp/ppp_generic.c | 51 +++++++++++++++++++++++++++++++++---------- 1 file changed, 39 insertions(+), 12 deletions(-) diff --git a/drivers/net/ppp/ppp_generic.c b/drivers/net/ppp/ppp_generic.c index ec83b83..7329c72 100644 --- a/drivers/net/ppp/ppp_generic.c +++ b/drivers/net/ppp/ppp_generic.c @@ -245,8 +245,8 @@ struct ppp_net { #define seq_after(a, b) ((s32)((a) - (b)) > 0) /* Prototypes. */ -static int ppp_unattached_ioctl(struct net *net, struct ppp_file *pf, - struct file *file, unsigned int cmd, unsigned long arg); +static int ppp_unattached_ioctl(struct net *net, struct file *file, + unsigned int cmd, unsigned long arg); static void ppp_xmit_process(struct ppp *ppp); static void ppp_send_frame(struct ppp *ppp, struct sk_buff *skb); static void ppp_push(struct ppp *ppp); @@ -584,12 +584,19 @@ static long ppp_ioctl(struct file *file, unsigned int cmd, unsigned long arg) void __user *argp = (void __user *)arg; int __user *p = argp; + switch (cmd) { + case PPPIOCNEWUNIT: + case PPPIOCATTACH: + case PPPIOCATTCHAN: + return ppp_unattached_ioctl(current->nsproxy->net_ns, file, + cmd, arg); + } + mutex_lock(&ppp_mutex); pf = file->private_data; if (!pf) { - err = ppp_unattached_ioctl(current->nsproxy->net_ns, - pf, file, cmd, arg); + err = -ENOTTY; goto out; } @@ -838,8 +845,8 @@ out: return err; } -static int ppp_unattached_ioctl(struct net *net, struct ppp_file *pf, - struct file *file, unsigned int cmd, unsigned long arg) +static int ppp_unattached_ioctl(struct net *net, struct file *file, + unsigned int cmd, unsigned long arg) { int unit, err = -EFAULT; struct ppp *ppp; @@ -867,31 +874,43 @@ static int ppp_unattached_ioctl(struct net *net, struct ppp_file *pf, /* Attach to an existing ppp unit */ if (get_user(unit, p)) break; + err = -ENXIO; pn = ppp_pernet(net); + mutex_lock(&ppp_mutex); mutex_lock(&pn->all_ppp_mutex); ppp = ppp_find_unit(pn, unit); if (ppp) { - atomic_inc(&ppp->file.refcnt); - file->private_data = &ppp->file; - err = 0; + err = -ENOTTY; + if (!file->private_data) { + atomic_inc(&ppp->file.refcnt); + file->private_data = &ppp->file; + err = 0; + } } mutex_unlock(&pn->all_ppp_mutex); + mutex_unlock(&ppp_mutex); break; case PPPIOCATTCHAN: if (get_user(unit, p)) break; + err = -ENXIO; pn = ppp_pernet(net); + mutex_lock(&ppp_mutex); spin_lock_bh(&pn->all_channels_lock); chan = ppp_find_channel(pn, unit); if (chan) { - atomic_inc(&chan->file.refcnt); - file->private_data = &chan->file; - err = 0; + err = -ENOTTY; + if (!file->private_data) { + atomic_inc(&chan->file.refcnt); + file->private_data = &chan->file; + err = 0; + } } spin_unlock_bh(&pn->all_channels_lock); + mutex_unlock(&ppp_mutex); break; default: @@ -2772,9 +2791,15 @@ static int ppp_create_interface(struct net *net, struct file *file, int *unit) */ dev_net_set(dev, net); + mutex_lock(&ppp_mutex); rtnl_lock(); mutex_lock(&pn->all_ppp_mutex); + if (file->private_data) { + ret = -ENOTTY; + goto out2; + } + if (*unit < 0) { ret = unit_get(&pn->units_idr, ppp); if (ret < 0) @@ -2818,12 +2843,14 @@ static int ppp_create_interface(struct net *net, struct file *file, int *unit) mutex_unlock(&pn->all_ppp_mutex); rtnl_unlock(); + mutex_unlock(&ppp_mutex); return 0; out2: mutex_unlock(&pn->all_ppp_mutex); rtnl_unlock(); + mutex_unlock(&ppp_mutex); free_netdev(dev); out1: return ret; -- 2.8.0.rc3 -- To unsubscribe from this list: send the line "unsubscribe linux-ppp" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html