UPSTREAM: ppp: defer netns reference release for ppp channel
authorWANG Cong <xiyou.wangcong@gmail.com>
Wed, 6 Jul 2016 05:12:36 +0000 (22:12 -0700)
committerAmit Pundir <amit.pundir@linaro.org>
Mon, 25 Jul 2016 12:12:59 +0000 (17:42 +0530)
(cherry pick from commit 205e1e255c479f3fd77446415706463b282f94e4)

Matt reported that we have a NULL pointer dereference
in ppp_pernet() from ppp_connect_channel(),
i.e. pch->chan_net is NULL.

This is due to that a parallel ppp_unregister_channel()
could happen while we are in ppp_connect_channel(), during
which pch->chan_net set to NULL. Since we need a reference
to net per channel, it makes sense to sync the refcnt
with the life time of the channel, therefore we should
release this reference when we destroy it.

Fixes: 1f461dcdd296 ("ppp: take reference on channels netns")
Reported-by: Matt Bennett <Matt.Bennett@alliedtelesis.co.nz>
Cc: Paul Mackerras <paulus@samba.org>
Cc: linux-ppp@vger.kernel.org
Cc: Guillaume Nault <g.nault@alphalink.fr>
Cc: Cyrill Gorcunov <gorcunov@openvz.org>
Signed-off-by: Cong Wang <xiyou.wangcong@gmail.com>
Reviewed-by: Cyrill Gorcunov <gorcunov@openvz.org>
Signed-off-by: David S. Miller <davem@davemloft.net>
Fixes: Change-Id: Iee0015eca5bd181954bb4896a3720f7549c5ed0b ("UPSTREAM:
ppp: take reference on channels netns")
Signed-off-by: Amit Pundir <amit.pundir@linaro.org>
Change-Id: I24d0bb6f349ab3829f63cfe935ed97b6913a3508

drivers/net/ppp/ppp_generic.c

index afe6fddd2baa03f671ec8740544450319230edaa..50cda254b57a472c2441b7dd3c864addbb2731a4 100644 (file)
@@ -2387,8 +2387,6 @@ ppp_unregister_channel(struct ppp_channel *chan)
        spin_lock_bh(&pn->all_channels_lock);
        list_del(&pch->list);
        spin_unlock_bh(&pn->all_channels_lock);
-       put_net(pch->chan_net);
-       pch->chan_net = NULL;
 
        pch->file.dead = 1;
        wake_up_interruptible(&pch->file.rwait);
@@ -2980,6 +2978,9 @@ ppp_disconnect_channel(struct channel *pch)
  */
 static void ppp_destroy_channel(struct channel *pch)
 {
+       put_net(pch->chan_net);
+       pch->chan_net = NULL;
+
        atomic_dec(&channel_count);
 
        if (!pch->file.dead) {