dccp: annotate data-races in dccp_poll()
authorEric Dumazet <edumazet@google.com>
Fri, 18 Aug 2023 01:58:20 +0000 (01:58 +0000)
committerJakub Kicinski <kuba@kernel.org>
Sat, 19 Aug 2023 02:30:24 +0000 (19:30 -0700)
We changed tcp_poll() over time, bug never updated dccp.

Note that we also could remove dccp instead of maintaining it.

Fixes: 7c657876b63c ("[DCCP]: Initial implementation")
Signed-off-by: Eric Dumazet <edumazet@google.com>
Link: https://lore.kernel.org/r/20230818015820.2701595-1-edumazet@google.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
net/dccp/proto.c

index 4e3266e..fcc5c9d 100644 (file)
@@ -315,11 +315,15 @@ EXPORT_SYMBOL_GPL(dccp_disconnect);
 __poll_t dccp_poll(struct file *file, struct socket *sock,
                       poll_table *wait)
 {
-       __poll_t mask;
        struct sock *sk = sock->sk;
+       __poll_t mask;
+       u8 shutdown;
+       int state;
 
        sock_poll_wait(file, sock, wait);
-       if (sk->sk_state == DCCP_LISTEN)
+
+       state = inet_sk_state_load(sk);
+       if (state == DCCP_LISTEN)
                return inet_csk_listen_poll(sk);
 
        /* Socket is not locked. We are protected from async events
@@ -328,20 +332,21 @@ __poll_t dccp_poll(struct file *file, struct socket *sock,
         */
 
        mask = 0;
-       if (sk->sk_err)
+       if (READ_ONCE(sk->sk_err))
                mask = EPOLLERR;
+       shutdown = READ_ONCE(sk->sk_shutdown);
 
-       if (sk->sk_shutdown == SHUTDOWN_MASK || sk->sk_state == DCCP_CLOSED)
+       if (shutdown == SHUTDOWN_MASK || state == DCCP_CLOSED)
                mask |= EPOLLHUP;
-       if (sk->sk_shutdown & RCV_SHUTDOWN)
+       if (shutdown & RCV_SHUTDOWN)
                mask |= EPOLLIN | EPOLLRDNORM | EPOLLRDHUP;
 
        /* Connected? */
-       if ((1 << sk->sk_state) & ~(DCCPF_REQUESTING | DCCPF_RESPOND)) {
+       if ((1 << state) & ~(DCCPF_REQUESTING | DCCPF_RESPOND)) {
                if (atomic_read(&sk->sk_rmem_alloc) > 0)
                        mask |= EPOLLIN | EPOLLRDNORM;
 
-               if (!(sk->sk_shutdown & SEND_SHUTDOWN)) {
+               if (!(shutdown & SEND_SHUTDOWN)) {
                        if (sk_stream_is_writeable(sk)) {
                                mask |= EPOLLOUT | EPOLLWRNORM;
                        } else {  /* send SIGIO later */
@@ -359,7 +364,6 @@ __poll_t dccp_poll(struct file *file, struct socket *sock,
        }
        return mask;
 }
-
 EXPORT_SYMBOL_GPL(dccp_poll);
 
 int dccp_ioctl(struct sock *sk, int cmd, int *karg)