]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
l2tp: fix l2tp_session_register with colliding l2tpv3 IDs
authorJames Chapman <jchapman@katalix.com>
Tue, 9 Jul 2024 16:28:39 +0000 (17:28 +0100)
committerDavid S. Miller <davem@davemloft.net>
Fri, 12 Jul 2024 03:09:18 +0000 (04:09 +0100)
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 <jchapman@katalix.com>
Signed-off-by: Tom Parkin <tparkin@katalix.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
net/l2tp/l2tp_core.c

index 29dfbd70c79c0028aefb7e29672dba4ddef5b63d..1c1decce7f06c744e7979241b19a56ceeb1de993 100644 (file)
@@ -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);