Re: [PATCH net] l2tp: fix tunnel and session refcount leak on seq_file release
Eric Dumazet <[email protected]>
| Newsgroups | org.kernel.vger.netdev |
|---|---|
| Message-ID | <CANn89i+i1gL5WvmbkedXm03NcoV0RC7ATd1GiLt=Mj5Y_tSDwg@mail.gmail.com> |
On Fri, Aug 7, 2026 at 7:10 PM Eric Dumazet <[email protected]> wrote: > > In pppol2tp_proc_open() and l2tp_dfs_seq_open(), iteration state > (pd->tunnel and pd->session) is kept in seq_file private data to allow > iteration across multiple read() system calls. > > However, if userspace closes /proc/net/pppol2tp or /sys/kernel/debug/l2tp/tunnels > before reading to end-of-file (EOF), any tunnel or session reference stored in > pd->tunnel / pd->session is left un-dropped when seq_file private data is freed. > > Fix this by dropping any remaining pd->tunnel and pd->session references in > pppol2tp_proc_release() and l2tp_dfs_seq_release() when closing the file. > > Fixes: 0e0c3fee3a59 ("l2tp: hold reference on tunnels printed in pppol2tp proc file") > Fixes: f726214d9b23 ("l2tp: hold reference on tunnels printed in l2tp/tunnels debugfs file") > Reported-by: [email protected] > Closes: https://lore.kernel.org/netdev/[email protected]/T/#u > Assisted-by: Jetski:Gemini-3.1-Pro > Cc: James Chapman <[email protected]> > Cc: Guillaume Nault <[email protected]> > Signed-off-by: Eric Dumazet <[email protected]> > --- > net/l2tp/l2tp_debugfs.c | 4 ++++ > net/l2tp/l2tp_ppp.c | 38 ++++++++++++++++++++++++++++++++++++-- > 2 files changed, 40 insertions(+), 2 deletions(-) > > diff --git a/net/l2tp/l2tp_debugfs.c b/net/l2tp/l2tp_debugfs.c > index b26986fda9d6cf096519d56032fe3deb5034c7c8..c12d5e1ee550ccc2608b6128cb653ca373280373 100644 > --- a/net/l2tp/l2tp_debugfs.c > +++ b/net/l2tp/l2tp_debugfs.c > @@ -306,6 +306,10 @@ static int l2tp_dfs_seq_release(struct inode *inode, struct file *file) > > seq = file->private_data; > pd = seq->private; > + if (pd->session) > + l2tp_session_put(pd->session); > + if (pd->tunnel) > + l2tp_tunnel_put(pd->tunnel); > if (pd->net) > put_net_track(pd->net, &pd->ns_tracker); > kfree(pd); > diff --git a/net/l2tp/l2tp_ppp.c b/net/l2tp/l2tp_ppp.c > index f8881699e1cad88e6f312e6ca47ae0af94c6137c..24e5bc06f65c6134974612294e36dd13c1608607 100644 > --- a/net/l2tp/l2tp_ppp.c > +++ b/net/l2tp/l2tp_ppp.c > @@ -1597,6 +1597,40 @@ static const struct seq_operations pppol2tp_seq_ops = { > .stop = pppol2tp_seq_stop, > .show = pppol2tp_seq_show, > }; > + > +static int pppol2tp_proc_open(struct inode *inode, struct file *file) > +{ > + struct net *net = pde_data(inode); > + struct pppol2tp_seq_data *pd; > + > + pd = __seq_open_private(file, &pppol2tp_seq_ops, sizeof(*pd)); > + if (!pd) > + return -ENOMEM; > + > + pd->p.net = get_net_track(net, &pd->p.ns_tracker, GFP_KERNEL); Oh well, we have a dependency against CONFIG_NET_NS for this stuff. pw-bot: cr