summaryrefslogtreecommitdiff
path: root/drivers/net/ppp
diff options
context:
space:
mode:
authorPaolo Abeni <pabeni@redhat.com>2026-07-20 09:18:11 +0200
committerPaolo Abeni <pabeni@redhat.com>2026-07-20 09:18:11 +0200
commit298bb2b8903323f6ef2eab4819a2e477765f0ff1 (patch)
treef1cf02687ba2434059d95d4ef3f2cc810acf50ca /drivers/net/ppp
parent285fd588859f42b14f6f455faaa336b4077c3a87 (diff)
parente13caf1c26587434f0b768193100440939c0fb91 (diff)
downloadlinux-next-298bb2b8903323f6ef2eab4819a2e477765f0ff1.tar.gz
linux-next-298bb2b8903323f6ef2eab4819a2e477765f0ff1.zip
Merge git://git.kernel.org/pub/scm/linux/kernel/git/netdev/net
Cross-merge networking fixes after downstream PR (net-7.2-rc4). No conflicts. Signed-off-by: Paolo Abeni <pabeni@redhat.com>
Diffstat (limited to 'drivers/net/ppp')
-rw-r--r--drivers/net/ppp/ppp_generic.c18
1 files changed, 15 insertions, 3 deletions
diff --git a/drivers/net/ppp/ppp_generic.c b/drivers/net/ppp/ppp_generic.c
index 57c68efa5ff8..717c1d3aa953 100644
--- a/drivers/net/ppp/ppp_generic.c
+++ b/drivers/net/ppp/ppp_generic.c
@@ -184,6 +184,7 @@ struct channel {
struct list_head clist; /* link in list of channels per unit */
spinlock_t upl; /* protects `ppp' and 'bridge' */
struct channel __rcu *bridge; /* "bridged" ppp channel */
+ struct rcu_head rcu; /* for RCU-deferred free of the channel */
#ifdef CONFIG_PPP_MULTILINK
u8 avail; /* flag used in multilink stuff */
u8 had_frag; /* >= 1 fragments have been sent */
@@ -3562,6 +3563,18 @@ ppp_disconnect_channel(struct channel *pch)
return err;
}
+/* Purge after the grace period: a late ppp_input() may still queue an
+ * skb on pch->file.rq before the last RCU reader drains.
+ */
+static void ppp_release_channel_free(struct rcu_head *rcu)
+{
+ struct channel *pch = container_of(rcu, struct channel, rcu);
+
+ skb_queue_purge(&pch->file.xq);
+ skb_queue_purge(&pch->file.rq);
+ kfree(pch);
+}
+
/*
* Drop a reference to a ppp channel and free its memory if the refcount reaches
* zero.
@@ -3581,9 +3594,7 @@ static void ppp_release_channel(struct channel *pch)
pr_err("ppp: destroying undead channel %p !\n", pch);
return;
}
- skb_queue_purge(&pch->file.xq);
- skb_queue_purge(&pch->file.rq);
- kfree(pch);
+ call_rcu(&pch->rcu, ppp_release_channel_free);
}
static void __exit ppp_cleanup(void)
@@ -3596,6 +3607,7 @@ static void __exit ppp_cleanup(void)
device_destroy(&ppp_class, MKDEV(PPP_MAJOR, 0));
class_unregister(&ppp_class);
unregister_pernet_device(&ppp_net_ops);
+ rcu_barrier(); /* wait for RCU callbacks before module unload */
}
/*