udp: Drop socket lock for encapsulated packets
authorHerbert Xu <herbert@gondor.apana.org.au>
Thu, 28 Aug 2008 05:40:04 +0000 (22:40 -0700)
committerGreg Kroah-Hartman <gregkh@suse.de>
Mon, 8 Sep 2008 11:44:24 +0000 (04:44 -0700)
[ Upstream commit d97106ea52aa57e63ff40d04479016836bbb5a4e ]

The socket lock is there to protect the normal UDP receive path.
Encapsulation UDP sockets don't need that protection.  In fact
the locking is deadly for them as they may contain another UDP
packet within, possibly with the same addresses.

Also the nested bit was copied from TCP.  TCP needs it because
of accept(2) spawning sockets.  This simply doesn't apply to UDP
so I've removed it.

Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
Signed-off-by: David S. Miller <davem@davemloft.net>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
net/ipv4/udp.c
net/ipv6/udp.c

index 9f3f7bade279a5081813ca39358c5f306195f2ee..b6e7ec006168997e4aa99da9de988336c33ccd90 100644 (file)
@@ -988,7 +988,9 @@ int udp_queue_rcv_skb(struct sock * sk, struct sk_buff *skb)
                    up->encap_rcv != NULL) {
                        int ret;
 
+                       bh_unlock_sock(sk);
                        ret = (*up->encap_rcv)(sk, skb);
+                       bh_lock_sock(sk);
                        if (ret <= 0) {
                                UDP_INC_STATS_BH(UDP_MIB_INDATAGRAMS,
                                                 is_udplite);
@@ -1087,7 +1089,7 @@ static int __udp4_lib_mcast_deliver(struct sk_buff *skb,
                        if (skb1) {
                                int ret = 0;
 
-                               bh_lock_sock_nested(sk);
+                               bh_lock_sock(sk);
                                if (!sock_owned_by_user(sk))
                                        ret = udp_queue_rcv_skb(sk, skb1);
                                else
@@ -1187,7 +1189,7 @@ int __udp4_lib_rcv(struct sk_buff *skb, struct hlist_head udptable[],
 
        if (sk != NULL) {
                int ret = 0;
-               bh_lock_sock_nested(sk);
+               bh_lock_sock(sk);
                if (!sock_owned_by_user(sk))
                        ret = udp_queue_rcv_skb(sk, skb);
                else
index dd309626ae9a737442aa1268c7a5f151507e7536..e14aa665a22b2d1309925374e1caa2fc8a0b88f4 100644 (file)
@@ -376,7 +376,7 @@ static int __udp6_lib_mcast_deliver(struct sk_buff *skb, struct in6_addr *saddr,
                                        uh->source, saddr, dif))) {
                struct sk_buff *buff = skb_clone(skb, GFP_ATOMIC);
                if (buff) {
-                       bh_lock_sock_nested(sk2);
+                       bh_lock_sock(sk2);
                        if (!sock_owned_by_user(sk2))
                                udpv6_queue_rcv_skb(sk2, buff);
                        else
@@ -384,7 +384,7 @@ static int __udp6_lib_mcast_deliver(struct sk_buff *skb, struct in6_addr *saddr,
                        bh_unlock_sock(sk2);
                }
        }
-       bh_lock_sock_nested(sk);
+       bh_lock_sock(sk);
        if (!sock_owned_by_user(sk))
                udpv6_queue_rcv_skb(sk, skb);
        else
@@ -502,7 +502,7 @@ int __udp6_lib_rcv(struct sk_buff *skb, struct hlist_head udptable[],
 
        /* deliver */
 
-       bh_lock_sock_nested(sk);
+       bh_lock_sock(sk);
        if (!sock_owned_by_user(sk))
                udpv6_queue_rcv_skb(sk, skb);
        else