@@ -329,39 +329,56 @@ static int l2tp_session_add_to_tunnel(struct l2tp_tunnel *tunnel,
329329 struct hlist_head * g_head ;
330330 struct hlist_head * head ;
331331 struct l2tp_net * pn ;
332+ int err ;
332333
333334 head = l2tp_session_id_hash (tunnel , session -> session_id );
334335
335336 write_lock_bh (& tunnel -> hlist_lock );
337+ if (!tunnel -> acpt_newsess ) {
338+ err = - ENODEV ;
339+ goto err_tlock ;
340+ }
341+
336342 hlist_for_each_entry (session_walk , head , hlist )
337- if (session_walk -> session_id == session -> session_id )
338- goto exist ;
343+ if (session_walk -> session_id == session -> session_id ) {
344+ err = - EEXIST ;
345+ goto err_tlock ;
346+ }
339347
340348 if (tunnel -> version == L2TP_HDR_VER_3 ) {
341349 pn = l2tp_pernet (tunnel -> l2tp_net );
342350 g_head = l2tp_session_id_hash_2 (l2tp_pernet (tunnel -> l2tp_net ),
343351 session -> session_id );
344352
345353 spin_lock_bh (& pn -> l2tp_session_hlist_lock );
354+
346355 hlist_for_each_entry (session_walk , g_head , global_hlist )
347- if (session_walk -> session_id == session -> session_id )
348- goto exist_glob ;
356+ if (session_walk -> session_id == session -> session_id ) {
357+ err = - EEXIST ;
358+ goto err_tlock_pnlock ;
359+ }
349360
361+ l2tp_tunnel_inc_refcount (tunnel );
362+ sock_hold (tunnel -> sock );
350363 hlist_add_head_rcu (& session -> global_hlist , g_head );
364+
351365 spin_unlock_bh (& pn -> l2tp_session_hlist_lock );
366+ } else {
367+ l2tp_tunnel_inc_refcount (tunnel );
368+ sock_hold (tunnel -> sock );
352369 }
353370
354371 hlist_add_head (& session -> hlist , head );
355372 write_unlock_bh (& tunnel -> hlist_lock );
356373
357374 return 0 ;
358375
359- exist_glob :
376+ err_tlock_pnlock :
360377 spin_unlock_bh (& pn -> l2tp_session_hlist_lock );
361- exist :
378+ err_tlock :
362379 write_unlock_bh (& tunnel -> hlist_lock );
363380
364- return - EEXIST ;
381+ return err ;
365382}
366383
367384/* Lookup a tunnel by id
@@ -1251,7 +1268,6 @@ static void l2tp_tunnel_destruct(struct sock *sk)
12511268 /* Remove hooks into tunnel socket */
12521269 sk -> sk_destruct = tunnel -> old_sk_destruct ;
12531270 sk -> sk_user_data = NULL ;
1254- tunnel -> sock = NULL ;
12551271
12561272 /* Remove the tunnel struct from the tunnel list */
12571273 pn = l2tp_pernet (tunnel -> l2tp_net );
@@ -1261,6 +1277,8 @@ static void l2tp_tunnel_destruct(struct sock *sk)
12611277 atomic_dec (& l2tp_tunnel_count );
12621278
12631279 l2tp_tunnel_closeall (tunnel );
1280+
1281+ tunnel -> sock = NULL ;
12641282 l2tp_tunnel_dec_refcount (tunnel );
12651283
12661284 /* Call the original destructor */
@@ -1285,6 +1303,7 @@ void l2tp_tunnel_closeall(struct l2tp_tunnel *tunnel)
12851303 tunnel -> name );
12861304
12871305 write_lock_bh (& tunnel -> hlist_lock );
1306+ tunnel -> acpt_newsess = false;
12881307 for (hash = 0 ; hash < L2TP_HASH_SIZE ; hash ++ ) {
12891308again :
12901309 hlist_for_each_safe (walk , tmp , & tunnel -> session_hlist [hash ]) {
@@ -1581,6 +1600,7 @@ int l2tp_tunnel_create(struct net *net, int fd, int version, u32 tunnel_id, u32
15811600 tunnel -> magic = L2TP_TUNNEL_MAGIC ;
15821601 sprintf (& tunnel -> name [0 ], "tunl %u" , tunnel_id );
15831602 rwlock_init (& tunnel -> hlist_lock );
1603+ tunnel -> acpt_newsess = true;
15841604
15851605 /* The net we belong to */
15861606 tunnel -> l2tp_net = net ;
@@ -1829,11 +1849,6 @@ struct l2tp_session *l2tp_session_create(int priv_size, struct l2tp_tunnel *tunn
18291849 return ERR_PTR (err );
18301850 }
18311851
1832- l2tp_tunnel_inc_refcount (tunnel );
1833-
1834- /* Ensure tunnel socket isn't deleted */
1835- sock_hold (tunnel -> sock );
1836-
18371852 /* Ignore management session in session count value */
18381853 if (session -> session_id != 0 )
18391854 atomic_inc (& l2tp_session_count );
0 commit comments