[PATCH net-next] ppp: tear down bridge before clearing pch->chan
Qingfang Deng <[email protected]> Fri, 10 Apr 2026 17:38:56 +0800
| Newsgroups | gmane.linux.kernel,gmane.linux.ppp,gmane.linux.network |
|---|---|
| Message-ID | <[email protected]> |
As we previously did to ppp_disconnect_channel(), also move ppp_unbridge_channels() before pch->chan is set to NULL in ppp_unregister_channel(). ppp_unbridge_channels() calls synchronize_rcu(), so no concurrent RCU readers in ppp_channel_bridge_input() can observe the channel after its chan pointer is cleared. This makes the !pchb->chan check in ppp_channel_bridge_input() redundant and can be safely removed. Signed-off-by: Qingfang Deng <[email protected]> --- drivers/net/ppp/ppp_generic.c | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/drivers/net/ppp/ppp_generic.c b/drivers/net/ppp/ppp_generic.c index b097d1b38ac9..3a609d48a424 100644 --- a/drivers/net/ppp/ppp_generic.c +++ b/drivers/net/ppp/ppp_generic.c @@ -2285,17 +2285,11 @@ static bool ppp_channel_bridge_input(struct channel *pch, struct sk_buff *skb) goto out_rcu; spin_lock_bh(&pchb->downl); - if (!pchb->chan) { - /* channel got unregistered */ - kfree_skb(skb); - goto outl; - } skb_scrub_packet(skb, !net_eq(pch->chan_net, pchb->chan_net)); if (!pchb->chan->ops->start_xmit(pchb->chan, skb)) kfree_skb(skb); -outl: spin_unlock_bh(&pchb->downl); out_rcu: rcu_read_unlock(); @@ -2997,6 +2991,8 @@ ppp_unregister_channel(struct ppp_channel *chan) * the channel's start_xmit or ioctl routine before we proceed. */ ppp_disconnect_channel(pch); + ppp_unbridge_channels(pch); + down_write(&pch->chan_sem); spin_lock_bh(&pch->downl); pch->chan = NULL; @@ -3008,8 +3004,6 @@ ppp_unregister_channel(struct ppp_channel *chan) list_del(&pch->list); spin_unlock_bh(&pn->all_channels_lock); - ppp_unbridge_channels(pch); - pch->file.dead = 1; wake_up_interruptible(&pch->file.rwait); -- 2.43.0