diff mbox

tcp: possible race between tcp_done() and tcp_poll()

Message ID 34d952a3-77cd-ea53-c3e3-ccde91d5cf63@jp.fujitsu.com
State Changes Requested, archived
Delegated to: David Miller
Headers show

Commit Message

Seiichi Ikarashi March 29, 2017, 5:22 a.m. UTC
Similar to commit a4d258036ed9b2a1811.

Between receiving a packet and tcp_poll(), sk->sk_err is protected by memory barriers but
sk->sk_shutdown and sk->sk_state are not. So possibly, POLLIN|POLLRDNORM|POLLRDHUP might
not be set even when receiving a RST packet.

Signed-off-by: Seiichi Ikarashi <s.ikarashi@jp.fujitsu.com>

 net/ipv4/tcp.c | 7 +++++--
 1 file changed, 5 insertions(+), 2 deletions(-)

Comments

Sergei Shtylyov March 29, 2017, 11:57 a.m. UTC | #1
Hello!

On 3/29/2017 8:22 AM, Seiichi Ikarashi wrote:

> Similar to commit a4d258036ed9b2a1811.

    Commit citing is standardized: it should specify 12-digit (at least) SHA1 
and the commit summary line enclosed in ("").

> Between receiving a packet and tcp_poll(), sk->sk_err is protected by memory barriers but
> sk->sk_shutdown and sk->sk_state are not. So possibly, POLLIN|POLLRDNORM|POLLRDHUP might
> not be set even when receiving a RST packet.
>
> Signed-off-by: Seiichi Ikarashi <s.ikarashi@jp.fujitsu.com>
>

     Should be --- before the diffstat.

>  net/ipv4/tcp.c | 7 +++++--
>  1 file changed, 5 insertions(+), 2 deletions(-)

[...]

MBR, Sergei
Seiichi Ikarashi March 29, 2017, 11:19 p.m. UTC | #2
Thanks Sergei!

On 2017-03-29 20:57, Sergei Shtylyov wrote:
> Hello!
> 
> On 3/29/2017 8:22 AM, Seiichi Ikarashi wrote:
> 
>> Similar to commit a4d258036ed9b2a1811.
> 
>    Commit citing is standardized: it should specify 12-digit (at least) SHA1 and the commit summary line enclosed in ("").
> 
>> Between receiving a packet and tcp_poll(), sk->sk_err is protected by memory barriers but
>> sk->sk_shutdown and sk->sk_state are not. So possibly, POLLIN|POLLRDNORM|POLLRDHUP might
>> not be set even when receiving a RST packet.
>>
>> Signed-off-by: Seiichi Ikarashi <s.ikarashi@jp.fujitsu.com>
>>
> 
>     Should be --- before the diffstat.

I'll resend.

Seiichi Ikarashi
diff mbox

Patch

diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c
index cf45555..c8bc86e 100644
--- a/net/ipv4/tcp.c
+++ b/net/ipv4/tcp.c
@@ -456,6 +456,8 @@  unsigned int tcp_poll(struct file *file, struct socket *sock, poll_table *wait)
 
 	sock_poll_wait(file, sk_sleep(sk), wait);
 
+	/* This barrier is coupled with smp_wmb() in tcp_reset() */
+	smp_rmb();
 	state = sk_state_load(sk);
 	if (state == TCP_LISTEN)
 		return inet_csk_listen_poll(sk);
@@ -540,8 +542,6 @@  unsigned int tcp_poll(struct file *file, struct socket *sock, poll_table *wait)
 		 */
 		mask |= POLLOUT | POLLWRNORM;
 	}
-	/* This barrier is coupled with smp_wmb() in tcp_reset() */
-	smp_rmb();
 	if (sk->sk_err || !skb_queue_empty(&sk->sk_error_queue))
 		mask |= POLLERR;
 
@@ -3291,6 +3291,9 @@  void tcp_done(struct sock *sk)
 
 	sk->sk_shutdown = SHUTDOWN_MASK;
 
+	/* This barrier is coupled with smp_rmb() in tcp_poll() */
+	smp_wmb();
+
 	if (!sock_flag(sk, SOCK_DEAD))
 		sk->sk_state_change(sk);
 	else