From: James Chapman Date: Tue, 9 Jul 2024 16:28:39 +0000 (+0100) Subject: l2tp: fix l2tp_session_register with colliding l2tpv3 IDs X-Git-Tag: v6.11-rc1~163^2~41 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=2146b7dd354c2a1384381ca3cd5751bfff6137d6;p=thirdparty%2Fkernel%2Fstable.git l2tp: fix l2tp_session_register with colliding l2tpv3 IDs When handling colliding L2TPv3 session IDs, we use the existing session IDR entry and link the new session on that using session->coll_list. However, when using an existing IDR entry, we must not do the idr_replace step. Fixes: aa5e17e1f5ec ("l2tp: store l2tpv3 sessions in per-net IDR") Signed-off-by: James Chapman Signed-off-by: Tom Parkin Signed-off-by: David S. Miller --- diff --git a/net/l2tp/l2tp_core.c b/net/l2tp/l2tp_core.c index 29dfbd70c79c0..1c1decce7f06c 100644 --- a/net/l2tp/l2tp_core.c +++ b/net/l2tp/l2tp_core.c @@ -436,6 +436,7 @@ int l2tp_session_register(struct l2tp_session *session, struct l2tp_tunnel *tunnel) { struct l2tp_net *pn = l2tp_pernet(tunnel->l2tp_net); + struct l2tp_session *other_session = NULL; u32 session_key; int err; @@ -456,11 +457,10 @@ int l2tp_session_register(struct l2tp_session *session, * support existing userspace which depends on it. */ if (err == -ENOSPC && tunnel->encap == L2TP_ENCAPTYPE_UDP) { - struct l2tp_session *session2; - - session2 = idr_find(&pn->l2tp_v3_session_idr, - session_key); - err = l2tp_session_collision_add(pn, session, session2); + other_session = idr_find(&pn->l2tp_v3_session_idr, + session_key); + err = l2tp_session_collision_add(pn, session, + other_session); } spin_unlock_bh(&pn->l2tp_session_idr_lock); } else { @@ -484,10 +484,12 @@ int l2tp_session_register(struct l2tp_session *session, spin_unlock_bh(&tunnel->list_lock); spin_lock_bh(&pn->l2tp_session_idr_lock); - if (tunnel->version == L2TP_HDR_VER_3) - idr_replace(&pn->l2tp_v3_session_idr, session, session_key); - else + if (tunnel->version == L2TP_HDR_VER_3) { + if (!other_session) + idr_replace(&pn->l2tp_v3_session_idr, session, session_key); + } else { idr_replace(&pn->l2tp_v2_session_idr, session, session_key); + } spin_unlock_bh(&pn->l2tp_session_idr_lock); trace_register_session(session);