]> git.ipfire.org Git - thirdparty/kernel/stable.git/commitdiff
udp: move udp->gro_enabled to udp->udp_flags
authorEric Dumazet <edumazet@google.com>
Tue, 12 Sep 2023 09:17:24 +0000 (09:17 +0000)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Wed, 10 Jan 2024 16:10:28 +0000 (17:10 +0100)
[ Upstream commit e1dc0615c6b08ef36414f08c011965b8fb56198b ]

syzbot reported that udp->gro_enabled can be read locklessly.
Use one atomic bit from udp->udp_flags.

Fixes: e20cf8d3f1f7 ("udp: implement GRO for plain UDP sockets.")
Reported-by: syzbot <syzkaller@googlegroups.com>
Signed-off-by: Eric Dumazet <edumazet@google.com>
Reviewed-by: Willem de Bruijn <willemb@google.com>
Signed-off-by: Paolo Abeni <pabeni@redhat.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
include/linux/udp.h
net/ipv4/udp.c
net/ipv4/udp_offload.c
net/ipv6/udp.c

index e6cd46e2b0831dad7d8e37343ff5a4089d5815bb..f87e2123fe7b0c68f7d912da50be9e2fa7f757cc 100644 (file)
@@ -34,6 +34,7 @@ enum {
        UDP_FLAGS_CORK,         /* Cork is required */
        UDP_FLAGS_NO_CHECK6_TX, /* Send zero UDP6 checksums on TX? */
        UDP_FLAGS_NO_CHECK6_RX, /* Allow zero UDP6 checksums on RX? */
+       UDP_FLAGS_GRO_ENABLED,  /* Request GRO aggregation */
 };
 
 struct udp_sock {
@@ -52,7 +53,6 @@ struct udp_sock {
                                           * different encapsulation layer set
                                           * this
                                           */
-                        gro_enabled:1, /* Request GRO aggregation */
                         accept_udp_l4:1,
                         accept_udp_fraglist:1;
 /* indicator bits used by pcflag: */
index 01e74919885adc07a036909a691919ff173e73a5..28292fcf070759541c834948672c0c7a6df50d06 100644 (file)
@@ -1901,7 +1901,7 @@ try_again:
                                                      (struct sockaddr *)sin);
        }
 
-       if (udp_sk(sk)->gro_enabled)
+       if (udp_test_bit(GRO_ENABLED, sk))
                udp_cmsg_recv(msg, sk, skb);
 
        if (inet->cmsg_flags)
@@ -2730,7 +2730,7 @@ int udp_lib_setsockopt(struct sock *sk, int level, int optname,
                /* when enabling GRO, accept the related GSO packet type */
                if (valbool)
                        udp_tunnel_encap_enable(sk->sk_socket);
-               up->gro_enabled = valbool;
+               udp_assign_bit(GRO_ENABLED, sk, valbool);
                up->accept_udp_l4 = valbool;
                release_sock(sk);
                break;
@@ -2820,7 +2820,7 @@ int udp_lib_getsockopt(struct sock *sk, int level, int optname,
                break;
 
        case UDP_GRO:
-               val = up->gro_enabled;
+               val = udp_test_bit(GRO_ENABLED, sk);
                break;
 
        /* The following two cannot be changed on UDP sockets, the return is
index 6d1a4bec2614df4f8b9ec5e6c387ab154d1f8d89..8096576fd9bde6558a9ea18c6cb8138bcc10be16 100644 (file)
@@ -549,10 +549,10 @@ struct sk_buff *udp_gro_receive(struct list_head *head, struct sk_buff *skb,
        NAPI_GRO_CB(skb)->is_flist = 0;
        if (!sk || !udp_sk(sk)->gro_receive) {
                if (skb->dev->features & NETIF_F_GRO_FRAGLIST)
-                       NAPI_GRO_CB(skb)->is_flist = sk ? !udp_sk(sk)->gro_enabled : 1;
+                       NAPI_GRO_CB(skb)->is_flist = sk ? !udp_test_bit(GRO_ENABLED, sk) : 1;
 
                if ((!sk && (skb->dev->features & NETIF_F_GRO_UDP_FWD)) ||
-                   (sk && udp_sk(sk)->gro_enabled) || NAPI_GRO_CB(skb)->is_flist)
+                   (sk && udp_test_bit(GRO_ENABLED, sk)) || NAPI_GRO_CB(skb)->is_flist)
                        return call_gro_receive(udp_gro_receive_segment, head, skb);
 
                /* no GRO, be sure flush the current packet */
index ae4f7f983f9519a458c30947a5d45d9e87289ee5..ddd17b5ea42591fedfa320aa1b576feb8f263978 100644 (file)
@@ -440,7 +440,7 @@ try_again:
                                                      (struct sockaddr *)sin6);
        }
 
-       if (udp_sk(sk)->gro_enabled)
+       if (udp_test_bit(GRO_ENABLED, sk))
                udp_cmsg_recv(msg, sk, skb);
 
        if (np->rxopt.all)