Gitweb:     
http://git.kernel.org/git/?p=linux/kernel/git/torvalds/linux-2.6.git;a=commit;h=27ab2568649d5ba6c5a20212079b7c4f6da4ca0d
Commit:     27ab2568649d5ba6c5a20212079b7c4f6da4ca0d
Parent:     c8fecf2242a0ab7230210665986b8ef915e1ae9e
Author:     Herbert Xu <[EMAIL PROTECTED]>
AuthorDate: Wed Dec 5 01:51:58 2007 -0800
Committer:  David S. Miller <[EMAIL PROTECTED]>
CommitDate: Mon Jan 28 14:56:32 2008 -0800

    [UDP]: Avoid repeated counting of checksum errors due to peeking
    
    Currently it is possible for two processes to peek on the same socket
    and end up incrementing the error counter twice for the same packet.
    
    This patch fixes it by making skb_kill_datagram return whether it
    succeeded in unlinking the packet and only incrementing the counter
    if it did.
    
    Signed-off-by: Herbert Xu <[EMAIL PROTECTED]>
    Signed-off-by: David S. Miller <[EMAIL PROTECTED]>
---
 include/linux/skbuff.h |    2 +-
 net/core/datagram.c    |    9 ++++++++-
 net/ipv4/udp.c         |    5 ++---
 net/ipv6/udp.c         |    4 ++--
 4 files changed, 13 insertions(+), 7 deletions(-)

diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h
index d39f53e..17b3f70 100644
--- a/include/linux/skbuff.h
+++ b/include/linux/skbuff.h
@@ -1549,7 +1549,7 @@ extern int               
skb_copy_and_csum_datagram_iovec(struct sk_buff *skb,
                                                        int hlen,
                                                        struct iovec *iov);
 extern void           skb_free_datagram(struct sock *sk, struct sk_buff *skb);
-extern void           skb_kill_datagram(struct sock *sk, struct sk_buff *skb,
+extern int            skb_kill_datagram(struct sock *sk, struct sk_buff *skb,
                                         unsigned int flags);
 extern __wsum         skb_checksum(const struct sk_buff *skb, int offset,
                                    int len, __wsum csum);
diff --git a/net/core/datagram.c b/net/core/datagram.c
index 029b93e..fbd6c76 100644
--- a/net/core/datagram.c
+++ b/net/core/datagram.c
@@ -217,20 +217,27 @@ void skb_free_datagram(struct sock *sk, struct sk_buff 
*skb)
  *     This function currently only disables BH when acquiring the
  *     sk_receive_queue lock.  Therefore it must not be used in a
  *     context where that lock is acquired in an IRQ context.
+ *
+ *     It returns 0 if the packet was removed by us.
  */
 
-void skb_kill_datagram(struct sock *sk, struct sk_buff *skb, unsigned int 
flags)
+int skb_kill_datagram(struct sock *sk, struct sk_buff *skb, unsigned int flags)
 {
+       int err = 0;
+
        if (flags & MSG_PEEK) {
+               err = -ENOENT;
                spin_lock_bh(&sk->sk_receive_queue.lock);
                if (skb == skb_peek(&sk->sk_receive_queue)) {
                        __skb_unlink(skb, &sk->sk_receive_queue);
                        atomic_dec(&skb->users);
+                       err = 0;
                }
                spin_unlock_bh(&sk->sk_receive_queue.lock);
        }
 
        kfree_skb(skb);
+       return err;
 }
 
 EXPORT_SYMBOL(skb_kill_datagram);
diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c
index d0283b7..f50de5d 100644
--- a/net/ipv4/udp.c
+++ b/net/ipv4/udp.c
@@ -899,9 +899,8 @@ out:
        return err;
 
 csum_copy_err:
-       UDP_INC_STATS_USER(UDP_MIB_INERRORS, is_udplite);
-
-       skb_kill_datagram(sk, skb, flags);
+       if (!skb_kill_datagram(sk, skb, flags))
+               UDP_INC_STATS_USER(UDP_MIB_INERRORS, is_udplite);
 
        if (noblock)
                return -EAGAIN;
diff --git a/net/ipv6/udp.c b/net/ipv6/udp.c
index 77ab31b..87bccec 100644
--- a/net/ipv6/udp.c
+++ b/net/ipv6/udp.c
@@ -207,8 +207,8 @@ out:
        return err;
 
 csum_copy_err:
-       UDP6_INC_STATS_USER(UDP_MIB_INERRORS, is_udplite);
-       skb_kill_datagram(sk, skb, flags);
+       if (!skb_kill_datagram(sk, skb, flags))
+               UDP6_INC_STATS_USER(UDP_MIB_INERRORS, is_udplite);
 
        if (flags & MSG_DONTWAIT)
                return -EAGAIN;
-
To unsubscribe from this list: send the line "unsubscribe git-commits-head" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to