* [PATCH net-next v2] l2tp: bump tunnel stats before dropping the session reference
@ 2026-11-03 8:42 Linkui Xiao
0 siblings, 0 replies; only message in thread
From: Linkui Xiao @ 2026-11-03 8:42 UTC (permalink / raw)
To: davem, edumazet, kuba, pabeni, horms, michael.bommarito, gnault,
alice.kernel, kuniyu, nicoyip.dev, mail
Cc: netdev, linux-kernel, Linkui Xiao
From: Linkui Xiao <xiaolinkui@kylinos.cn>
l2tp_udp_encap_recv() derives the tunnel pointer from the session it
has just looked up, so the session reference is the only thing keeping
the tunnel alive. Both error paths of the function drop the reference
before jumping to the invalid label, which still dereferences the
tunnel:
tunnel = session->tunnel;
if (version != tunnel->version) {
l2tp_session_put(session);
goto invalid;
}
...
invalid:
atomic_long_inc(&tunnel->stats.rx_invalid);
Reorder the error paths so the statistics are updated before the
reference is dropped, removing the dependency on the tunnel staying
allocated after its last reference is gone.
Currently this is safe by accident: the only live entry point is the
UDP encap_rcv hook, which is invoked under rcu_read_lock(), and the
tunnel is freed by kfree_rcu(), so the tunnel memory outlives the
dereference. Making the order explicitly correct keeps the function
safe regardless of the calling context, instead of relying on every
future caller holding an RCU read-side reference.
The put on the version mismatch path came later, with commit
4d10edfd1475 ("l2tp: Fix memleak in l2tp_udp_encap_recv()."), which
plugged a session leak.
Found by inspection.
Signed-off-by: Linkui Xiao <xiaolinkui@kylinos.cn>
---
Changes in v2:
- Describe the change as hardening instead of a reachable
use-after-free: the socket backlog path pointed at by the v1 commit
message cannot be reached, and the live receive path always holds an
RCU read-side reference, so the old ordering is currently safe
(Sashiko AI review).
- Drop the backport tags (the Fixes tag and the Cc to stable)
accordingly and retitle the patch.
- Correct the index line: the v1 patch carried the blob hashes of an
earlier draft of this change, so its new hash did not match the file
the diff actually produces.
v1:
- Link: https://lore.kernel.org/all/20261027063657.1359170-1-xiaolinkui@126.com/
net/l2tp/l2tp_core.c | 12 ++++++------
1 file changed, 6 insertions(+), 6 deletions(-)
diff --git a/net/l2tp/l2tp_core.c b/net/l2tp/l2tp_core.c
index 7e042a3e648c..b7183b527fc4 100644
--- a/net/l2tp/l2tp_core.c
+++ b/net/l2tp/l2tp_core.c
@@ -1083,16 +1083,12 @@ int l2tp_udp_encap_recv(struct sock *sk, struct sk_buff *skb)
tunnel = session->tunnel;
/* Check protocol version */
- if (version != tunnel->version) {
- l2tp_session_put(session);
+ if (version != tunnel->version)
goto invalid;
- }
if (version == L2TP_HDR_VER_3 &&
- l2tp_v3_ensure_opt_in_linear(session, skb, &ptr, &optr)) {
- l2tp_session_put(session);
+ l2tp_v3_ensure_opt_in_linear(session, skb, &ptr, &optr))
goto invalid;
- }
l2tp_recv_common(session, skb, ptr, optr, hdrflags, length);
l2tp_session_put(session);
@@ -1100,7 +1096,11 @@ int l2tp_udp_encap_recv(struct sock *sk, struct sk_buff *skb)
return 0;
invalid:
+ /* The session reference is the only thing keeping the tunnel alive
+ * here, so account the invalid packet before dropping it.
+ */
atomic_long_inc(&tunnel->stats.rx_invalid);
+ l2tp_session_put(session);
pass:
/* Put UDP header back */
--
2.25.1
^ permalink raw reply [flat|nested] only message in thread
only message in thread, other threads:[~2026-11-03 8:43 UTC | newest]
Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-11-03 8:42 [PATCH net-next v2] l2tp: bump tunnel stats before dropping the session reference Linkui Xiao
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®