net: Implement ->sock_is_readable() for UDP and AF_UNIX
authorCong Wang <cong.wang@bytedance.com>
Fri, 8 Oct 2021 20:33:05 +0000 (13:33 -0700)
committerAlexei Starovoitov <ast@kernel.org>
Tue, 26 Oct 2021 19:29:33 +0000 (12:29 -0700)
Yucong noticed we can't poll() sockets in sockmap even
when they are the destination sockets of redirections.
This is because we never poll any psock queues in ->poll(),
except for TCP. With ->sock_is_readable() now we can
overwrite >sock_is_readable(), invoke and implement it for
both UDP and AF_UNIX sockets.

Reported-by: Yucong Sun <sunyucong@gmail.com>
Signed-off-by: Cong Wang <cong.wang@bytedance.com>
Signed-off-by: Alexei Starovoitov <ast@kernel.org>
Link: https://lore.kernel.org/bpf/20211008203306.37525-4-xiyou.wangcong@gmail.com
net/ipv4/udp.c
net/ipv4/udp_bpf.c
net/unix/af_unix.c
net/unix/unix_bpf.c

index 8536b2a..2fffcf2 100644 (file)
@@ -2867,6 +2867,9 @@ __poll_t udp_poll(struct file *file, struct socket *sock, poll_table *wait)
            !(sk->sk_shutdown & RCV_SHUTDOWN) && first_packet_length(sk) == -1)
                mask &= ~(EPOLLIN | EPOLLRDNORM);
 
+       /* psock ingress_msg queue should not contain any bad checksum frames */
+       if (sk_is_readable(sk))
+               mask |= EPOLLIN | EPOLLRDNORM;
        return mask;
 
 }
index 7a1d5f4..bbe6569 100644 (file)
@@ -114,6 +114,7 @@ static void udp_bpf_rebuild_protos(struct proto *prot, const struct proto *base)
        *prot        = *base;
        prot->close  = sock_map_close;
        prot->recvmsg = udp_bpf_recvmsg;
+       prot->sock_is_readable = sk_msg_is_readable;
 }
 
 static void udp_bpf_check_v6_needs_rebuild(struct proto *ops)
index 89f9e85..78e08e8 100644 (file)
@@ -3052,6 +3052,8 @@ static __poll_t unix_poll(struct file *file, struct socket *sock, poll_table *wa
        /* readable? */
        if (!skb_queue_empty_lockless(&sk->sk_receive_queue))
                mask |= EPOLLIN | EPOLLRDNORM;
+       if (sk_is_readable(sk))
+               mask |= EPOLLIN | EPOLLRDNORM;
 
        /* Connection-based need to check for termination and startup */
        if ((sk->sk_type == SOCK_STREAM || sk->sk_type == SOCK_SEQPACKET) &&
@@ -3091,6 +3093,8 @@ static __poll_t unix_dgram_poll(struct file *file, struct socket *sock,
        /* readable? */
        if (!skb_queue_empty_lockless(&sk->sk_receive_queue))
                mask |= EPOLLIN | EPOLLRDNORM;
+       if (sk_is_readable(sk))
+               mask |= EPOLLIN | EPOLLRDNORM;
 
        /* Connection-based need to check for termination and startup */
        if (sk->sk_type == SOCK_SEQPACKET) {
index b927e2b..452376c 100644 (file)
@@ -102,6 +102,7 @@ static void unix_dgram_bpf_rebuild_protos(struct proto *prot, const struct proto
        *prot        = *base;
        prot->close  = sock_map_close;
        prot->recvmsg = unix_bpf_recvmsg;
+       prot->sock_is_readable = sk_msg_is_readable;
 }
 
 static void unix_stream_bpf_rebuild_protos(struct proto *prot,
@@ -110,6 +111,7 @@ static void unix_stream_bpf_rebuild_protos(struct proto *prot,
        *prot        = *base;
        prot->close  = sock_map_close;
        prot->recvmsg = unix_bpf_recvmsg;
+       prot->sock_is_readable = sk_msg_is_readable;
        prot->unhash  = sock_map_unhash;
 }