]> git.ipfire.org Git - thirdparty/kernel/stable.git/commitdiff
gro: remove rcu_read_lock/rcu_read_unlock from gro_receive handlers
authorEric Dumazet <edumazet@google.com>
Tue, 23 Nov 2021 22:56:07 +0000 (14:56 -0800)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Thu, 12 Sep 2024 09:06:47 +0000 (11:06 +0200)
[ Upstream commit fc1ca3348a74a1afaa7ffebc2b2f2cc149e11278 ]

All gro_receive() handlers are called from dev_gro_receive()
while rcu_read_lock() has been called.

There is no point stacking more rcu_read_lock()

Signed-off-by: Eric Dumazet <edumazet@google.com>
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
Stable-dep-of: 7e4196935069 ("fou: Fix null-ptr-deref in GRO.")
Signed-off-by: Sasha Levin <sashal@kernel.org>
drivers/net/geneve.c
net/8021q/vlan_core.c
net/ethernet/eth.c
net/ipv4/af_inet.c
net/ipv4/fou.c
net/ipv4/gre_offload.c
net/ipv4/udp_offload.c
net/ipv6/ip6_offload.c
net/ipv6/udp_offload.c

index af35361a3dcee905b9dbc2a27ead34a7b9040b90..17989688f54b0d637a41ffdbf4c30bdcff21b8c0 100644 (file)
@@ -528,18 +528,15 @@ static struct sk_buff *geneve_gro_receive(struct sock *sk,
 
        type = gh->proto_type;
 
-       rcu_read_lock();
        ptype = gro_find_receive_by_type(type);
        if (!ptype)
-               goto out_unlock;
+               goto out;
 
        skb_gro_pull(skb, gh_len);
        skb_gro_postpull_rcsum(skb, gh, gh_len);
        pp = call_gro_receive(ptype->callbacks.gro_receive, head, skb);
        flush = 0;
 
-out_unlock:
-       rcu_read_unlock();
 out:
        skb_gro_flush_final(skb, pp, flush);
 
index 43aea97c57620374ea4d62b870402eaed44153be..ff0d3fc82c0ff24fa8f3eae0b80b8acff8c7bf2b 100644 (file)
@@ -482,10 +482,9 @@ static struct sk_buff *vlan_gro_receive(struct list_head *head,
 
        type = vhdr->h_vlan_encapsulated_proto;
 
-       rcu_read_lock();
        ptype = gro_find_receive_by_type(type);
        if (!ptype)
-               goto out_unlock;
+               goto out;
 
        flush = 0;
 
@@ -504,8 +503,6 @@ static struct sk_buff *vlan_gro_receive(struct list_head *head,
        skb_gro_postpull_rcsum(skb, vhdr, sizeof(*vhdr));
        pp = call_gro_receive(ptype->callbacks.gro_receive, head, skb);
 
-out_unlock:
-       rcu_read_unlock();
 out:
        skb_gro_flush_final(skb, pp, flush);
 
index 61cb40368723c3277e1992172bf2ad6d897dd7e3..2b0eb24199d6486b655cf2d736c7742810b8c647 100644 (file)
@@ -430,19 +430,16 @@ struct sk_buff *eth_gro_receive(struct list_head *head, struct sk_buff *skb)
 
        type = eh->h_proto;
 
-       rcu_read_lock();
        ptype = gro_find_receive_by_type(type);
        if (ptype == NULL) {
                flush = 1;
-               goto out_unlock;
+               goto out;
        }
 
        skb_gro_pull(skb, sizeof(*eh));
        skb_gro_postpull_rcsum(skb, eh, sizeof(*eh));
        pp = call_gro_receive(ptype->callbacks.gro_receive, head, skb);
 
-out_unlock:
-       rcu_read_unlock();
 out:
        skb_gro_flush_final(skb, pp, flush);
 
index ce42626663de676763b93767286572f33fbf36f7..cac63bb20c16cfc9ba47d2ab9263f84085080b97 100644 (file)
@@ -1471,19 +1471,18 @@ struct sk_buff *inet_gro_receive(struct list_head *head, struct sk_buff *skb)
 
        proto = iph->protocol;
 
-       rcu_read_lock();
        ops = rcu_dereference(inet_offloads[proto]);
        if (!ops || !ops->callbacks.gro_receive)
-               goto out_unlock;
+               goto out;
 
        if (*(u8 *)iph != 0x45)
-               goto out_unlock;
+               goto out;
 
        if (ip_is_fragment(iph))
-               goto out_unlock;
+               goto out;
 
        if (unlikely(ip_fast_csum((u8 *)iph, 5)))
-               goto out_unlock;
+               goto out;
 
        id = ntohl(*(__be32 *)&iph->id);
        flush = (u16)((ntohl(*(__be32 *)iph) ^ skb_gro_len(skb)) | (id & ~IP_DF));
@@ -1560,9 +1559,6 @@ struct sk_buff *inet_gro_receive(struct list_head *head, struct sk_buff *skb)
        pp = indirect_call_gro_receive(tcp4_gro_receive, udp4_gro_receive,
                                       ops->callbacks.gro_receive, head, skb);
 
-out_unlock:
-       rcu_read_unlock();
-
 out:
        skb_gro_flush_final(skb, pp, flush);
 
index 8fcbc6258ec527f3069f7a525d33929c0ffa1bdf..5aacc75e495c4b4208befc00e069dad3ffbb153a 100644 (file)
@@ -246,17 +246,14 @@ static struct sk_buff *fou_gro_receive(struct sock *sk,
        /* Flag this frame as already having an outer encap header */
        NAPI_GRO_CB(skb)->is_fou = 1;
 
-       rcu_read_lock();
        offloads = NAPI_GRO_CB(skb)->is_ipv6 ? inet6_offloads : inet_offloads;
        ops = rcu_dereference(offloads[proto]);
        if (!ops || !ops->callbacks.gro_receive)
-               goto out_unlock;
+               goto out;
 
        pp = call_gro_receive(ops->callbacks.gro_receive, head, skb);
 
-out_unlock:
-       rcu_read_unlock();
-
+out:
        return pp;
 }
 
@@ -438,17 +435,14 @@ next_proto:
        /* Flag this frame as already having an outer encap header */
        NAPI_GRO_CB(skb)->is_fou = 1;
 
-       rcu_read_lock();
        offloads = NAPI_GRO_CB(skb)->is_ipv6 ? inet6_offloads : inet_offloads;
        ops = rcu_dereference(offloads[proto]);
        if (WARN_ON_ONCE(!ops || !ops->callbacks.gro_receive))
-               goto out_unlock;
+               goto out;
 
        pp = call_gro_receive(ops->callbacks.gro_receive, head, skb);
        flush = 0;
 
-out_unlock:
-       rcu_read_unlock();
 out:
        skb_gro_flush_final_remcsum(skb, pp, flush, &grc);
 
index e0a24657588721ac7b7279603025d876188b385d..e9dabf1affe9ed079ce0b0483670d48b18e5cd30 100644 (file)
@@ -158,10 +158,9 @@ static struct sk_buff *gre_gro_receive(struct list_head *head,
 
        type = greh->protocol;
 
-       rcu_read_lock();
        ptype = gro_find_receive_by_type(type);
        if (!ptype)
-               goto out_unlock;
+               goto out;
 
        grehlen = GRE_HEADER_SECTION;
 
@@ -175,13 +174,13 @@ static struct sk_buff *gre_gro_receive(struct list_head *head,
        if (skb_gro_header_hard(skb, hlen)) {
                greh = skb_gro_header_slow(skb, hlen, off);
                if (unlikely(!greh))
-                       goto out_unlock;
+                       goto out;
        }
 
        /* Don't bother verifying checksum if we're going to flush anyway. */
        if ((greh->flags & GRE_CSUM) && !NAPI_GRO_CB(skb)->flush) {
                if (skb_gro_checksum_simple_validate(skb))
-                       goto out_unlock;
+                       goto out;
 
                skb_gro_checksum_try_convert(skb, IPPROTO_GRE,
                                             null_compute_pseudo);
@@ -225,8 +224,6 @@ static struct sk_buff *gre_gro_receive(struct list_head *head,
        pp = call_gro_receive(ptype->callbacks.gro_receive, head, skb);
        flush = 0;
 
-out_unlock:
-       rcu_read_unlock();
 out:
        skb_gro_flush_final(skb, pp, flush);
 
index 57168d4fa1956adc2b0e1322ffc9146b2d8c6813..418da7a8a075588032e6b14fb41912355acb33f6 100644 (file)
@@ -606,13 +606,11 @@ struct sk_buff *udp4_gro_receive(struct list_head *head, struct sk_buff *skb)
                                             inet_gro_compute_pseudo);
 skip:
        NAPI_GRO_CB(skb)->is_ipv6 = 0;
-       rcu_read_lock();
 
        if (static_branch_unlikely(&udp_encap_needed_key))
                sk = udp4_gro_lookup_skb(skb, uh->source, uh->dest);
 
        pp = udp_gro_receive(head, skb, uh, sk);
-       rcu_read_unlock();
        return pp;
 
 flush:
index 15c8eef1ef443854e207bfaa238cb7aa321fedb9..f67921e0dd566f0be905062894955cce1de3280e 100644 (file)
@@ -209,7 +209,6 @@ INDIRECT_CALLABLE_SCOPE struct sk_buff *ipv6_gro_receive(struct list_head *head,
 
        flush += ntohs(iph->payload_len) != skb_gro_len(skb);
 
-       rcu_read_lock();
        proto = iph->nexthdr;
        ops = rcu_dereference(inet6_offloads[proto]);
        if (!ops || !ops->callbacks.gro_receive) {
@@ -222,7 +221,7 @@ INDIRECT_CALLABLE_SCOPE struct sk_buff *ipv6_gro_receive(struct list_head *head,
 
                ops = rcu_dereference(inet6_offloads[proto]);
                if (!ops || !ops->callbacks.gro_receive)
-                       goto out_unlock;
+                       goto out;
 
                iph = ipv6_hdr(skb);
        }
@@ -280,9 +279,6 @@ not_same_flow:
        pp = indirect_call_gro_receive_l4(tcp6_gro_receive, udp6_gro_receive,
                                         ops->callbacks.gro_receive, head, skb);
 
-out_unlock:
-       rcu_read_unlock();
-
 out:
        skb_gro_flush_final(skb, pp, flush);
 
index 7752e1e921f8f84e0ae26659bab710fcaa6fea5e..1107782c083d57065cea8d614e8bb567873b5e2a 100644 (file)
@@ -144,13 +144,11 @@ struct sk_buff *udp6_gro_receive(struct list_head *head, struct sk_buff *skb)
 
 skip:
        NAPI_GRO_CB(skb)->is_ipv6 = 1;
-       rcu_read_lock();
 
        if (static_branch_unlikely(&udpv6_encap_needed_key))
                sk = udp6_gro_lookup_skb(skb, uh->source, uh->dest);
 
        pp = udp_gro_receive(head, skb, uh, sk);
-       rcu_read_unlock();
        return pp;
 
 flush: