pppox: drain queued packets on channel handoff

PPPIOCGCHAN both returns the channel index and marks a PPPOX socket as
bound to generic PPP, despite its getter semantic. Packets received
before that transition are queued on sk_receive_queue, but a bound
socket is no longer readable. Such packets therefore remain queued until
the socket is destroyed.

After marking a socket bound, wait for receive paths that observed the
old state to finish queueing packets, and then drain the queue into
generic PPP.

Fixes: 1da177e4c3 ("Linux-2.6.12-rc2")
Signed-off-by: Qingfang Deng <qingfang.deng@linux.dev>
Link: https://patch.msgid.link/20260811035314.302878-1-qingfang.deng@linux.dev
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
This commit is contained in:
Qingfang Deng 2026-08-11 11:53:10 +08:00 committed by Jakub Kicinski
parent 4f1d06cf8a
commit 92c1bf630a

View File

@ -74,7 +74,9 @@ int pppox_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
switch (cmd) {
case PPPIOCGCHAN: {
struct sk_buff *skb;
int index;
rc = -ENOTCONN;
if (!(sk->sk_state & PPPOX_CONNECTED))
break;
@ -85,7 +87,22 @@ int pppox_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
break;
rc = 0;
/* PPPIOCGCHAN historically marks the userspace handoff to
* generic PPP; pppd then attaches the returned channel to
* /dev/ppp.
*/
sk->sk_state |= PPPOX_BOUND;
/* Let lockless receive paths finish queueing against the old
* state.
*/
synchronize_net();
/* Drain packets queued before the handoff because a bound
* socket is no longer readable.
*/
while ((skb = skb_dequeue(&sk->sk_receive_queue))) {
skb_orphan(skb);
ppp_input(&po->chan, skb);
}
break;
}
default: