122
122
struct pppol2tp_session {
123
123
int owner ; /* pid that opened the socket */
124
124
125
- struct sock * sock ; /* Pointer to the session
125
+ struct mutex sk_lock ; /* Protects .sk */
126
+ struct sock __rcu * sk ; /* Pointer to the session
126
127
* PPPoX socket */
128
+ struct sock * __sk ; /* Copy of .sk, for cleanup */
129
+ struct rcu_head rcu ; /* For asynchronous release */
127
130
struct sock * tunnel_sock ; /* Pointer to the tunnel UDP
128
131
* socket */
129
132
int flags ; /* accessed by PPPIOCGFLAGS.
@@ -138,6 +141,24 @@ static const struct ppp_channel_ops pppol2tp_chan_ops = {
138
141
139
142
static const struct proto_ops pppol2tp_ops ;
140
143
144
+ /* Retrieves the pppol2tp socket associated to a session.
145
+ * A reference is held on the returned socket, so this function must be paired
146
+ * with sock_put().
147
+ */
148
+ static struct sock * pppol2tp_session_get_sock (struct l2tp_session * session )
149
+ {
150
+ struct pppol2tp_session * ps = l2tp_session_priv (session );
151
+ struct sock * sk ;
152
+
153
+ rcu_read_lock ();
154
+ sk = rcu_dereference (ps -> sk );
155
+ if (sk )
156
+ sock_hold (sk );
157
+ rcu_read_unlock ();
158
+
159
+ return sk ;
160
+ }
161
+
141
162
/* Helpers to obtain tunnel/session contexts from sockets.
142
163
*/
143
164
static inline struct l2tp_session * pppol2tp_sock_to_session (struct sock * sk )
@@ -224,7 +245,8 @@ static void pppol2tp_recv(struct l2tp_session *session, struct sk_buff *skb, int
224
245
/* If the socket is bound, send it in to PPP's input queue. Otherwise
225
246
* queue it on the session socket.
226
247
*/
227
- sk = ps -> sock ;
248
+ rcu_read_lock ();
249
+ sk = rcu_dereference (ps -> sk );
228
250
if (sk == NULL )
229
251
goto no_sock ;
230
252
@@ -247,30 +269,16 @@ static void pppol2tp_recv(struct l2tp_session *session, struct sk_buff *skb, int
247
269
kfree_skb (skb );
248
270
}
249
271
}
272
+ rcu_read_unlock ();
250
273
251
274
return ;
252
275
253
276
no_sock :
277
+ rcu_read_unlock ();
254
278
l2tp_info (session , L2TP_MSG_DATA , "%s: no socket\n" , session -> name );
255
279
kfree_skb (skb );
256
280
}
257
281
258
- static void pppol2tp_session_sock_hold (struct l2tp_session * session )
259
- {
260
- struct pppol2tp_session * ps = l2tp_session_priv (session );
261
-
262
- if (ps -> sock )
263
- sock_hold (ps -> sock );
264
- }
265
-
266
- static void pppol2tp_session_sock_put (struct l2tp_session * session )
267
- {
268
- struct pppol2tp_session * ps = l2tp_session_priv (session );
269
-
270
- if (ps -> sock )
271
- sock_put (ps -> sock );
272
- }
273
-
274
282
/************************************************************************
275
283
* Transmit handling
276
284
***********************************************************************/
@@ -431,14 +439,16 @@ static int pppol2tp_xmit(struct ppp_channel *chan, struct sk_buff *skb)
431
439
*/
432
440
static void pppol2tp_session_close (struct l2tp_session * session )
433
441
{
434
- struct pppol2tp_session * ps = l2tp_session_priv (session );
435
- struct sock * sk = ps -> sock ;
436
- struct socket * sock = sk -> sk_socket ;
442
+ struct sock * sk ;
437
443
438
444
BUG_ON (session -> magic != L2TP_SESSION_MAGIC );
439
445
440
- if (sock )
441
- inet_shutdown (sock , SEND_SHUTDOWN );
446
+ sk = pppol2tp_session_get_sock (session );
447
+ if (sk ) {
448
+ if (sk -> sk_socket )
449
+ inet_shutdown (sk -> sk_socket , SEND_SHUTDOWN );
450
+ sock_put (sk );
451
+ }
442
452
443
453
/* Don't let the session go away before our socket does */
444
454
l2tp_session_inc_refcount (session );
@@ -461,6 +471,14 @@ static void pppol2tp_session_destruct(struct sock *sk)
461
471
}
462
472
}
463
473
474
+ static void pppol2tp_put_sk (struct rcu_head * head )
475
+ {
476
+ struct pppol2tp_session * ps ;
477
+
478
+ ps = container_of (head , typeof (* ps ), rcu );
479
+ sock_put (ps -> __sk );
480
+ }
481
+
464
482
/* Called when the PPPoX socket (session) is closed.
465
483
*/
466
484
static int pppol2tp_release (struct socket * sock )
@@ -486,11 +504,24 @@ static int pppol2tp_release(struct socket *sock)
486
504
487
505
session = pppol2tp_sock_to_session (sk );
488
506
489
- /* Purge any queued data */
490
507
if (session != NULL ) {
508
+ struct pppol2tp_session * ps ;
509
+
491
510
__l2tp_session_unhash (session );
492
511
l2tp_session_queue_purge (session );
493
- sock_put (sk );
512
+
513
+ ps = l2tp_session_priv (session );
514
+ mutex_lock (& ps -> sk_lock );
515
+ ps -> __sk = rcu_dereference_protected (ps -> sk ,
516
+ lockdep_is_held (& ps -> sk_lock ));
517
+ RCU_INIT_POINTER (ps -> sk , NULL );
518
+ mutex_unlock (& ps -> sk_lock );
519
+ call_rcu (& ps -> rcu , pppol2tp_put_sk );
520
+
521
+ /* Rely on the sock_put() call at the end of the function for
522
+ * dropping the reference held by pppol2tp_sock_to_session().
523
+ * The last reference will be dropped by pppol2tp_put_sk().
524
+ */
494
525
}
495
526
release_sock (sk );
496
527
@@ -557,12 +588,14 @@ static int pppol2tp_create(struct net *net, struct socket *sock, int kern)
557
588
static void pppol2tp_show (struct seq_file * m , void * arg )
558
589
{
559
590
struct l2tp_session * session = arg ;
560
- struct pppol2tp_session * ps = l2tp_session_priv (session );
591
+ struct sock * sk ;
592
+
593
+ sk = pppol2tp_session_get_sock (session );
594
+ if (sk ) {
595
+ struct pppox_sock * po = pppox_sk (sk );
561
596
562
- if (ps ) {
563
- struct pppox_sock * po = pppox_sk (ps -> sock );
564
- if (po )
565
- seq_printf (m , " interface %s\n" , ppp_dev_name (& po -> chan ));
597
+ seq_printf (m , " interface %s\n" , ppp_dev_name (& po -> chan ));
598
+ sock_put (sk );
566
599
}
567
600
}
568
601
#endif
@@ -693,13 +726,17 @@ static int pppol2tp_connect(struct socket *sock, struct sockaddr *uservaddr,
693
726
/* Using a pre-existing session is fine as long as it hasn't
694
727
* been connected yet.
695
728
*/
696
- if (ps -> sock ) {
729
+ mutex_lock (& ps -> sk_lock );
730
+ if (rcu_dereference_protected (ps -> sk ,
731
+ lockdep_is_held (& ps -> sk_lock ))) {
732
+ mutex_unlock (& ps -> sk_lock );
697
733
error = - EEXIST ;
698
734
goto end ;
699
735
}
700
736
701
737
/* consistency checks */
702
738
if (ps -> tunnel_sock != tunnel -> sock ) {
739
+ mutex_unlock (& ps -> sk_lock );
703
740
error = - EEXIST ;
704
741
goto end ;
705
742
}
@@ -716,19 +753,21 @@ static int pppol2tp_connect(struct socket *sock, struct sockaddr *uservaddr,
716
753
goto end ;
717
754
}
718
755
756
+ ps = l2tp_session_priv (session );
757
+ mutex_init (& ps -> sk_lock );
719
758
l2tp_session_inc_refcount (session );
759
+
760
+ mutex_lock (& ps -> sk_lock );
720
761
error = l2tp_session_register (session , tunnel );
721
762
if (error < 0 ) {
763
+ mutex_unlock (& ps -> sk_lock );
722
764
kfree (session );
723
765
goto end ;
724
766
}
725
767
drop_refcnt = true;
726
768
}
727
769
728
- /* Associate session with its PPPoL2TP socket */
729
- ps = l2tp_session_priv (session );
730
770
ps -> owner = current -> pid ;
731
- ps -> sock = sk ;
732
771
ps -> tunnel_sock = tunnel -> sock ;
733
772
734
773
session -> recv_skb = pppol2tp_recv ;
@@ -737,12 +776,6 @@ static int pppol2tp_connect(struct socket *sock, struct sockaddr *uservaddr,
737
776
session -> show = pppol2tp_show ;
738
777
#endif
739
778
740
- /* We need to know each time a skb is dropped from the reorder
741
- * queue.
742
- */
743
- session -> ref = pppol2tp_session_sock_hold ;
744
- session -> deref = pppol2tp_session_sock_put ;
745
-
746
779
/* If PMTU discovery was enabled, use the MTU that was discovered */
747
780
dst = sk_dst_get (tunnel -> sock );
748
781
if (dst != NULL ) {
@@ -776,12 +809,17 @@ static int pppol2tp_connect(struct socket *sock, struct sockaddr *uservaddr,
776
809
po -> chan .mtu = session -> mtu ;
777
810
778
811
error = ppp_register_net_channel (sock_net (sk ), & po -> chan );
779
- if (error )
812
+ if (error ) {
813
+ mutex_unlock (& ps -> sk_lock );
780
814
goto end ;
815
+ }
781
816
782
817
out_no_ppp :
783
818
/* This is how we get the session context from the socket. */
784
819
sk -> sk_user_data = session ;
820
+ rcu_assign_pointer (ps -> sk , sk );
821
+ mutex_unlock (& ps -> sk_lock );
822
+
785
823
sk -> sk_state = PPPOX_CONNECTED ;
786
824
l2tp_info (session , L2TP_MSG_CONTROL , "%s: created\n" ,
787
825
session -> name );
@@ -827,6 +865,7 @@ static int pppol2tp_session_create(struct net *net, struct l2tp_tunnel *tunnel,
827
865
}
828
866
829
867
ps = l2tp_session_priv (session );
868
+ mutex_init (& ps -> sk_lock );
830
869
ps -> tunnel_sock = tunnel -> sock ;
831
870
832
871
error = l2tp_session_register (session , tunnel );
@@ -998,12 +1037,10 @@ static int pppol2tp_session_ioctl(struct l2tp_session *session,
998
1037
"%s: pppol2tp_session_ioctl(cmd=%#x, arg=%#lx)\n" ,
999
1038
session -> name , cmd , arg );
1000
1039
1001
- sk = ps -> sock ;
1040
+ sk = pppol2tp_session_get_sock ( session ) ;
1002
1041
if (!sk )
1003
1042
return - EBADR ;
1004
1043
1005
- sock_hold (sk );
1006
-
1007
1044
switch (cmd ) {
1008
1045
case SIOCGIFMTU :
1009
1046
err = - ENXIO ;
@@ -1279,7 +1316,6 @@ static int pppol2tp_session_setsockopt(struct sock *sk,
1279
1316
int optname , int val )
1280
1317
{
1281
1318
int err = 0 ;
1282
- struct pppol2tp_session * ps = l2tp_session_priv (session );
1283
1319
1284
1320
switch (optname ) {
1285
1321
case PPPOL2TP_SO_RECVSEQ :
@@ -1300,8 +1336,8 @@ static int pppol2tp_session_setsockopt(struct sock *sk,
1300
1336
}
1301
1337
session -> send_seq = !!val ;
1302
1338
{
1303
- struct sock * ssk = ps -> sock ;
1304
- struct pppox_sock * po = pppox_sk ( ssk );
1339
+ struct pppox_sock * po = pppox_sk ( sk ) ;
1340
+
1305
1341
po -> chan .hdrlen = val ? PPPOL2TP_L2TP_HDR_SIZE_SEQ :
1306
1342
PPPOL2TP_L2TP_HDR_SIZE_NOSEQ ;
1307
1343
}
@@ -1640,8 +1676,9 @@ static void pppol2tp_seq_session_show(struct seq_file *m, void *v)
1640
1676
{
1641
1677
struct l2tp_session * session = v ;
1642
1678
struct l2tp_tunnel * tunnel = session -> tunnel ;
1643
- struct pppol2tp_session * ps = l2tp_session_priv (session );
1644
- struct pppox_sock * po = pppox_sk (ps -> sock );
1679
+ unsigned char state ;
1680
+ char user_data_ok ;
1681
+ struct sock * sk ;
1645
1682
u32 ip = 0 ;
1646
1683
u16 port = 0 ;
1647
1684
@@ -1651,16 +1688,23 @@ static void pppol2tp_seq_session_show(struct seq_file *m, void *v)
1651
1688
port = ntohs (inet -> inet_sport );
1652
1689
}
1653
1690
1691
+ sk = pppol2tp_session_get_sock (session );
1692
+ if (sk ) {
1693
+ state = sk -> sk_state ;
1694
+ user_data_ok = (session == sk -> sk_user_data ) ? 'Y' : 'N' ;
1695
+ } else {
1696
+ state = 0 ;
1697
+ user_data_ok = 'N' ;
1698
+ }
1699
+
1654
1700
seq_printf (m , " SESSION '%s' %08X/%d %04X/%04X -> "
1655
1701
"%04X/%04X %d %c\n" ,
1656
1702
session -> name , ip , port ,
1657
1703
tunnel -> tunnel_id ,
1658
1704
session -> session_id ,
1659
1705
tunnel -> peer_tunnel_id ,
1660
1706
session -> peer_session_id ,
1661
- ps -> sock -> sk_state ,
1662
- (session == ps -> sock -> sk_user_data ) ?
1663
- 'Y' : 'N' );
1707
+ state , user_data_ok );
1664
1708
seq_printf (m , " %d/%d/%c/%c/%s %08x %u\n" ,
1665
1709
session -> mtu , session -> mru ,
1666
1710
session -> recv_seq ? 'R' : '-' ,
@@ -1677,8 +1721,12 @@ static void pppol2tp_seq_session_show(struct seq_file *m, void *v)
1677
1721
atomic_long_read (& session -> stats .rx_bytes ),
1678
1722
atomic_long_read (& session -> stats .rx_errors ));
1679
1723
1680
- if (po )
1724
+ if (sk ) {
1725
+ struct pppox_sock * po = pppox_sk (sk );
1726
+
1681
1727
seq_printf (m , " interface %s\n" , ppp_dev_name (& po -> chan ));
1728
+ sock_put (sk );
1729
+ }
1682
1730
}
1683
1731
1684
1732
static int pppol2tp_seq_show (struct seq_file * m , void * v )
0 commit comments