@@ -221,15 +221,9 @@ static inline int unix_may_send(struct sock *sk, struct sock *osk)
221
221
return unix_peer (osk ) == NULL || unix_our_peer (sk , osk );
222
222
}
223
223
224
- static inline int unix_recvq_full (const struct sock * sk )
225
- {
226
- return skb_queue_len (& sk -> sk_receive_queue ) > sk -> sk_max_ack_backlog ;
227
- }
228
-
229
224
static inline int unix_recvq_full_lockless (const struct sock * sk )
230
225
{
231
- return skb_queue_len_lockless (& sk -> sk_receive_queue ) >
232
- READ_ONCE (sk -> sk_max_ack_backlog );
226
+ return skb_queue_len_lockless (& sk -> sk_receive_queue ) > sk -> sk_max_ack_backlog ;
233
227
}
234
228
235
229
struct sock * unix_peer_get (struct sock * s )
@@ -530,18 +524,18 @@ static int unix_dgram_peer_wake_me(struct sock *sk, struct sock *other)
530
524
return 0 ;
531
525
}
532
526
533
- static int unix_writable (const struct sock * sk )
527
+ static int unix_writable (const struct sock * sk , unsigned char state )
534
528
{
535
- return sk -> sk_state != TCP_LISTEN &&
536
- (refcount_read (& sk -> sk_wmem_alloc ) << 2 ) <= sk -> sk_sndbuf ;
529
+ return state != TCP_LISTEN &&
530
+ (refcount_read (& sk -> sk_wmem_alloc ) << 2 ) <= READ_ONCE ( sk -> sk_sndbuf ) ;
537
531
}
538
532
539
533
static void unix_write_space (struct sock * sk )
540
534
{
541
535
struct socket_wq * wq ;
542
536
543
537
rcu_read_lock ();
544
- if (unix_writable (sk )) {
538
+ if (unix_writable (sk , READ_ONCE ( sk -> sk_state ) )) {
545
539
wq = rcu_dereference (sk -> sk_wq );
546
540
if (skwq_has_sleeper (wq ))
547
541
wake_up_interruptible_sync_poll (& wq -> wait ,
@@ -570,7 +564,6 @@ static void unix_dgram_disconnected(struct sock *sk, struct sock *other)
570
564
sk_error_report (other );
571
565
}
572
566
}
573
- other -> sk_state = TCP_CLOSE ;
574
567
}
575
568
576
569
static void unix_sock_destructor (struct sock * sk )
@@ -617,7 +610,7 @@ static void unix_release_sock(struct sock *sk, int embrion)
617
610
u -> path .dentry = NULL ;
618
611
u -> path .mnt = NULL ;
619
612
state = sk -> sk_state ;
620
- sk -> sk_state = TCP_CLOSE ;
613
+ WRITE_ONCE ( sk -> sk_state , TCP_CLOSE ) ;
621
614
622
615
skpair = unix_peer (sk );
623
616
unix_peer (sk ) = NULL ;
@@ -638,7 +631,7 @@ static void unix_release_sock(struct sock *sk, int embrion)
638
631
unix_state_lock (skpair );
639
632
/* No more writes */
640
633
WRITE_ONCE (skpair -> sk_shutdown , SHUTDOWN_MASK );
641
- if (!skb_queue_empty (& sk -> sk_receive_queue ) || embrion )
634
+ if (!skb_queue_empty_lockless (& sk -> sk_receive_queue ) || embrion )
642
635
WRITE_ONCE (skpair -> sk_err , ECONNRESET );
643
636
unix_state_unlock (skpair );
644
637
skpair -> sk_state_change (skpair );
@@ -739,7 +732,8 @@ static int unix_listen(struct socket *sock, int backlog)
739
732
if (backlog > sk -> sk_max_ack_backlog )
740
733
wake_up_interruptible_all (& u -> peer_wait );
741
734
sk -> sk_max_ack_backlog = backlog ;
742
- sk -> sk_state = TCP_LISTEN ;
735
+ WRITE_ONCE (sk -> sk_state , TCP_LISTEN );
736
+
743
737
/* set credentials so connect can copy them */
744
738
init_peercred (sk );
745
739
err = 0 ;
@@ -976,7 +970,7 @@ static struct sock *unix_create1(struct net *net, struct socket *sock, int kern,
976
970
sk -> sk_hash = unix_unbound_hash (sk );
977
971
sk -> sk_allocation = GFP_KERNEL_ACCOUNT ;
978
972
sk -> sk_write_space = unix_write_space ;
979
- sk -> sk_max_ack_backlog = net -> unx .sysctl_max_dgram_qlen ;
973
+ sk -> sk_max_ack_backlog = READ_ONCE ( net -> unx .sysctl_max_dgram_qlen ) ;
980
974
sk -> sk_destruct = unix_sock_destructor ;
981
975
u = unix_sk (sk );
982
976
u -> listener = NULL ;
@@ -1402,7 +1396,8 @@ static int unix_dgram_connect(struct socket *sock, struct sockaddr *addr,
1402
1396
if (err )
1403
1397
goto out_unlock ;
1404
1398
1405
- sk -> sk_state = other -> sk_state = TCP_ESTABLISHED ;
1399
+ WRITE_ONCE (sk -> sk_state , TCP_ESTABLISHED );
1400
+ WRITE_ONCE (other -> sk_state , TCP_ESTABLISHED );
1406
1401
} else {
1407
1402
/*
1408
1403
* 1003.1g breaking connected state with AF_UNSPEC
@@ -1419,13 +1414,20 @@ static int unix_dgram_connect(struct socket *sock, struct sockaddr *addr,
1419
1414
1420
1415
unix_peer (sk ) = other ;
1421
1416
if (!other )
1422
- sk -> sk_state = TCP_CLOSE ;
1417
+ WRITE_ONCE ( sk -> sk_state , TCP_CLOSE ) ;
1423
1418
unix_dgram_peer_wake_disconnect_wakeup (sk , old_peer );
1424
1419
1425
1420
unix_state_double_unlock (sk , other );
1426
1421
1427
- if (other != old_peer )
1422
+ if (other != old_peer ) {
1428
1423
unix_dgram_disconnected (sk , old_peer );
1424
+
1425
+ unix_state_lock (old_peer );
1426
+ if (!unix_peer (old_peer ))
1427
+ WRITE_ONCE (old_peer -> sk_state , TCP_CLOSE );
1428
+ unix_state_unlock (old_peer );
1429
+ }
1430
+
1429
1431
sock_put (old_peer );
1430
1432
} else {
1431
1433
unix_peer (sk ) = other ;
@@ -1473,7 +1475,6 @@ static int unix_stream_connect(struct socket *sock, struct sockaddr *uaddr,
1473
1475
struct sk_buff * skb = NULL ;
1474
1476
long timeo ;
1475
1477
int err ;
1476
- int st ;
1477
1478
1478
1479
err = unix_validate_addr (sunaddr , addr_len );
1479
1480
if (err )
@@ -1538,7 +1539,7 @@ static int unix_stream_connect(struct socket *sock, struct sockaddr *uaddr,
1538
1539
if (other -> sk_shutdown & RCV_SHUTDOWN )
1539
1540
goto out_unlock ;
1540
1541
1541
- if (unix_recvq_full (other )) {
1542
+ if (unix_recvq_full_lockless (other )) {
1542
1543
err = - EAGAIN ;
1543
1544
if (!timeo )
1544
1545
goto out_unlock ;
@@ -1563,9 +1564,7 @@ static int unix_stream_connect(struct socket *sock, struct sockaddr *uaddr,
1563
1564
1564
1565
Well, and we have to recheck the state after socket locked.
1565
1566
*/
1566
- st = sk -> sk_state ;
1567
-
1568
- switch (st ) {
1567
+ switch (READ_ONCE (sk -> sk_state )) {
1569
1568
case TCP_CLOSE :
1570
1569
/* This is ok... continue with connect */
1571
1570
break ;
@@ -1580,7 +1579,7 @@ static int unix_stream_connect(struct socket *sock, struct sockaddr *uaddr,
1580
1579
1581
1580
unix_state_lock_nested (sk , U_LOCK_SECOND );
1582
1581
1583
- if (sk -> sk_state != st ) {
1582
+ if (sk -> sk_state != TCP_CLOSE ) {
1584
1583
unix_state_unlock (sk );
1585
1584
unix_state_unlock (other );
1586
1585
sock_put (other );
@@ -1633,7 +1632,7 @@ static int unix_stream_connect(struct socket *sock, struct sockaddr *uaddr,
1633
1632
copy_peercred (sk , other );
1634
1633
1635
1634
sock -> state = SS_CONNECTED ;
1636
- sk -> sk_state = TCP_ESTABLISHED ;
1635
+ WRITE_ONCE ( sk -> sk_state , TCP_ESTABLISHED ) ;
1637
1636
sock_hold (newsk );
1638
1637
1639
1638
smp_mb__after_atomic (); /* sock_hold() does an atomic_inc() */
@@ -1705,7 +1704,7 @@ static int unix_accept(struct socket *sock, struct socket *newsock,
1705
1704
goto out ;
1706
1705
1707
1706
arg -> err = - EINVAL ;
1708
- if (sk -> sk_state != TCP_LISTEN )
1707
+ if (READ_ONCE ( sk -> sk_state ) != TCP_LISTEN )
1709
1708
goto out ;
1710
1709
1711
1710
/* If socket state is TCP_LISTEN it cannot change (for now...),
@@ -1962,7 +1961,7 @@ static int unix_dgram_sendmsg(struct socket *sock, struct msghdr *msg,
1962
1961
}
1963
1962
1964
1963
err = - EMSGSIZE ;
1965
- if (len > sk -> sk_sndbuf - 32 )
1964
+ if (len > READ_ONCE ( sk -> sk_sndbuf ) - 32 )
1966
1965
goto out ;
1967
1966
1968
1967
if (len > SKB_MAX_ALLOC ) {
@@ -2044,7 +2043,7 @@ static int unix_dgram_sendmsg(struct socket *sock, struct msghdr *msg,
2044
2043
unix_peer (sk ) = NULL ;
2045
2044
unix_dgram_peer_wake_disconnect_wakeup (sk , other );
2046
2045
2047
- sk -> sk_state = TCP_CLOSE ;
2046
+ WRITE_ONCE ( sk -> sk_state , TCP_CLOSE ) ;
2048
2047
unix_state_unlock (sk );
2049
2048
2050
2049
unix_dgram_disconnected (sk , other );
@@ -2221,7 +2220,7 @@ static int unix_stream_sendmsg(struct socket *sock, struct msghdr *msg,
2221
2220
}
2222
2221
2223
2222
if (msg -> msg_namelen ) {
2224
- err = sk -> sk_state == TCP_ESTABLISHED ? - EISCONN : - EOPNOTSUPP ;
2223
+ err = READ_ONCE ( sk -> sk_state ) == TCP_ESTABLISHED ? - EISCONN : - EOPNOTSUPP ;
2225
2224
goto out_err ;
2226
2225
} else {
2227
2226
err = - ENOTCONN ;
@@ -2242,7 +2241,7 @@ static int unix_stream_sendmsg(struct socket *sock, struct msghdr *msg,
2242
2241
& err , 0 );
2243
2242
} else {
2244
2243
/* Keep two messages in the pipe so it schedules better */
2245
- size = min_t (int , size , (sk -> sk_sndbuf >> 1 ) - 64 );
2244
+ size = min_t (int , size , (READ_ONCE ( sk -> sk_sndbuf ) >> 1 ) - 64 );
2246
2245
2247
2246
/* allow fallback to order-0 allocations */
2248
2247
size = min_t (int , size , SKB_MAX_HEAD (0 ) + UNIX_SKB_FRAGS_SZ );
@@ -2335,7 +2334,7 @@ static int unix_seqpacket_sendmsg(struct socket *sock, struct msghdr *msg,
2335
2334
if (err )
2336
2335
return err ;
2337
2336
2338
- if (sk -> sk_state != TCP_ESTABLISHED )
2337
+ if (READ_ONCE ( sk -> sk_state ) != TCP_ESTABLISHED )
2339
2338
return - ENOTCONN ;
2340
2339
2341
2340
if (msg -> msg_namelen )
@@ -2349,7 +2348,7 @@ static int unix_seqpacket_recvmsg(struct socket *sock, struct msghdr *msg,
2349
2348
{
2350
2349
struct sock * sk = sock -> sk ;
2351
2350
2352
- if (sk -> sk_state != TCP_ESTABLISHED )
2351
+ if (READ_ONCE ( sk -> sk_state ) != TCP_ESTABLISHED )
2353
2352
return - ENOTCONN ;
2354
2353
2355
2354
return unix_dgram_recvmsg (sock , msg , size , flags );
@@ -2654,7 +2653,7 @@ static struct sk_buff *manage_oob(struct sk_buff *skb, struct sock *sk,
2654
2653
2655
2654
static int unix_stream_read_skb (struct sock * sk , skb_read_actor_t recv_actor )
2656
2655
{
2657
- if (unlikely (sk -> sk_state != TCP_ESTABLISHED ))
2656
+ if (unlikely (READ_ONCE ( sk -> sk_state ) != TCP_ESTABLISHED ))
2658
2657
return - ENOTCONN ;
2659
2658
2660
2659
return unix_read_skb (sk , recv_actor );
@@ -2678,7 +2677,7 @@ static int unix_stream_read_generic(struct unix_stream_read_state *state,
2678
2677
size_t size = state -> size ;
2679
2678
unsigned int last_len ;
2680
2679
2681
- if (unlikely (sk -> sk_state != TCP_ESTABLISHED )) {
2680
+ if (unlikely (READ_ONCE ( sk -> sk_state ) != TCP_ESTABLISHED )) {
2682
2681
err = - EINVAL ;
2683
2682
goto out ;
2684
2683
}
@@ -3009,7 +3008,7 @@ long unix_inq_len(struct sock *sk)
3009
3008
struct sk_buff * skb ;
3010
3009
long amount = 0 ;
3011
3010
3012
- if (sk -> sk_state == TCP_LISTEN )
3011
+ if (READ_ONCE ( sk -> sk_state ) == TCP_LISTEN )
3013
3012
return - EINVAL ;
3014
3013
3015
3014
spin_lock (& sk -> sk_receive_queue .lock );
@@ -3121,12 +3120,14 @@ static int unix_compat_ioctl(struct socket *sock, unsigned int cmd, unsigned lon
3121
3120
static __poll_t unix_poll (struct file * file , struct socket * sock , poll_table * wait )
3122
3121
{
3123
3122
struct sock * sk = sock -> sk ;
3123
+ unsigned char state ;
3124
3124
__poll_t mask ;
3125
3125
u8 shutdown ;
3126
3126
3127
3127
sock_poll_wait (file , sock , wait );
3128
3128
mask = 0 ;
3129
3129
shutdown = READ_ONCE (sk -> sk_shutdown );
3130
+ state = READ_ONCE (sk -> sk_state );
3130
3131
3131
3132
/* exceptional events? */
3132
3133
if (READ_ONCE (sk -> sk_err ))
@@ -3148,14 +3149,14 @@ static __poll_t unix_poll(struct file *file, struct socket *sock, poll_table *wa
3148
3149
3149
3150
/* Connection-based need to check for termination and startup */
3150
3151
if ((sk -> sk_type == SOCK_STREAM || sk -> sk_type == SOCK_SEQPACKET ) &&
3151
- sk -> sk_state == TCP_CLOSE )
3152
+ state == TCP_CLOSE )
3152
3153
mask |= EPOLLHUP ;
3153
3154
3154
3155
/*
3155
3156
* we set writable also when the other side has shut down the
3156
3157
* connection. This prevents stuck sockets.
3157
3158
*/
3158
- if (unix_writable (sk ))
3159
+ if (unix_writable (sk , state ))
3159
3160
mask |= EPOLLOUT | EPOLLWRNORM | EPOLLWRBAND ;
3160
3161
3161
3162
return mask ;
@@ -3166,12 +3167,14 @@ static __poll_t unix_dgram_poll(struct file *file, struct socket *sock,
3166
3167
{
3167
3168
struct sock * sk = sock -> sk , * other ;
3168
3169
unsigned int writable ;
3170
+ unsigned char state ;
3169
3171
__poll_t mask ;
3170
3172
u8 shutdown ;
3171
3173
3172
3174
sock_poll_wait (file , sock , wait );
3173
3175
mask = 0 ;
3174
3176
shutdown = READ_ONCE (sk -> sk_shutdown );
3177
+ state = READ_ONCE (sk -> sk_state );
3175
3178
3176
3179
/* exceptional events? */
3177
3180
if (READ_ONCE (sk -> sk_err ) ||
@@ -3191,19 +3194,14 @@ static __poll_t unix_dgram_poll(struct file *file, struct socket *sock,
3191
3194
mask |= EPOLLIN | EPOLLRDNORM ;
3192
3195
3193
3196
/* Connection-based need to check for termination and startup */
3194
- if (sk -> sk_type == SOCK_SEQPACKET ) {
3195
- if (sk -> sk_state == TCP_CLOSE )
3196
- mask |= EPOLLHUP ;
3197
- /* connection hasn't started yet? */
3198
- if (sk -> sk_state == TCP_SYN_SENT )
3199
- return mask ;
3200
- }
3197
+ if (sk -> sk_type == SOCK_SEQPACKET && state == TCP_CLOSE )
3198
+ mask |= EPOLLHUP ;
3201
3199
3202
3200
/* No write status requested, avoid expensive OUT tests. */
3203
3201
if (!(poll_requested_events (wait ) & (EPOLLWRBAND |EPOLLWRNORM |EPOLLOUT )))
3204
3202
return mask ;
3205
3203
3206
- writable = unix_writable (sk );
3204
+ writable = unix_writable (sk , state );
3207
3205
if (writable ) {
3208
3206
unix_state_lock (sk );
3209
3207
0 commit comments