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
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.