linux/net/l2tp
Michael Bommarito 979c017803 l2tp: use list_del_rcu in l2tp_session_unhash
An unprivileged local user can pin a host CPU indefinitely in
l2tp_session_get_by_ifname() by issuing L2TP_CMD_SESSION_GET on
L2TP_ATTR_IFNAME concurrently with L2TP_CMD_SESSION_CREATE and
L2TP_CMD_SESSION_DELETE on the same tunnel. All three commands take
GENL_UNS_ADMIN_PERM, so CAP_NET_ADMIN in the netns user namespace
suffices; on any host that has l2tp_core loaded the trigger is
reachable from a standard `unshare -Urn` sandbox.

l2tp_session_unhash() removes a session from tunnel->session_list
with list_del_init(), but that list is walked by
l2tp_session_get_by_ifname() with list_for_each_entry_rcu() under
rcu_read_lock_bh(). list_del_init() leaves the deleted entry's
next/prev self-pointing; a reader that has loaded the entry and
then advances pos->list.next reads &session->list, container_of()s
back to the same session, and list_for_each_entry_rcu() never
reaches the list head. The CPU stays in strcmp() inside the
walker, with BH and preemption disabled, so RCU grace periods on
the host stall behind it and the wedged thread cannot be killed
(SIGKILL is delivered on syscall return).

Use list_del_rcu() to match the existing list_add_rcu() in
l2tp_session_register(); the deleted session remains visible to
in-flight walkers with consistent next/prev pointers until
kfree_rcu() in l2tp_session_free() releases it. tunnel->session_list
has exactly one list_del_init() call site; the list_del_init
(&session->clist) at l2tp_core.c:533 operates on the per-collision
list, which is not walked under RCU. list_empty(&session->list) is
not used anywhere in net/l2tp/ after the unhash point, so dropping
the post-delete self-init is safe; the fix has no userspace-visible
behavior change.

Fixes: 89b768ec2d ("l2tp: use rcu list add/del when updating lists")
Cc: stable@vger.kernel.org # 6.11+
Signed-off-by: Michael Bommarito <michael.bommarito@gmail.com>
Link: https://patch.msgid.link/20260518183447.64078-1-michael.bommarito@gmail.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
2026-05-21 08:47:20 -07:00
..
Kconfig ipv6: convert CONFIG_IPV6 to built-in only and clean up Kconfigs 2026-03-29 11:21:22 -07:00
l2tp_core.c l2tp: use list_del_rcu in l2tp_session_unhash 2026-05-21 08:47:20 -07:00
l2tp_core.h l2tp: improve tunnel/session refcount helpers 2024-08-11 04:38:50 +01:00
l2tp_debugfs.c Convert 'alloc_obj' family to use the new default GFP_KERNEL argument 2026-02-21 17:09:51 -08:00
l2tp_eth.c net: l2tp_eth: Replace deprecated strcpy with strscpy in l2tp_eth_create 2026-02-24 13:38:33 +01:00
l2tp_ip.c net: remove addr_len argument of recvmsg() handlers 2026-03-02 18:17:17 -08:00
l2tp_ip6.c net: remove addr_len argument of recvmsg() handlers 2026-03-02 18:17:17 -08:00
l2tp_netlink.c genetlink: hold RCU in genlmsg_mcast() 2024-10-15 17:52:58 -07:00
l2tp_ppp.c l2tp: ppp: use max L2TP header size for PPP channel hdrlen 2026-03-19 11:00:04 +01:00
Makefile l2tp: add tracepoint infrastructure to core 2020-08-22 12:44:37 -07:00
trace.h l2tp: add tracepoint definitions in trace.h 2020-08-22 12:44:37 -07:00